grep-components 2.22.2 → 2.23.0-GREPF-2943.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -60,6 +60,10 @@ import { $isElementNode, $caretFromPoint, $isExtendableTextPointCaret, $extendCa
60
60
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
61
61
  import FormatBold from '@mui/icons-material/FormatBold';
62
62
  import FormatItalic from '@mui/icons-material/FormatItalic';
63
+ import FormatSuperscript from '@mui/icons-material/Superscript';
64
+ import FormatSubscript from '@mui/icons-material/Subscript';
65
+ import { CharacterLimitPlugin } from '@lexical/react/LexicalCharacterLimitPlugin';
66
+ import DOMPurify from 'dompurify';
63
67
  import Dialog from '@mui/material/Dialog';
64
68
  import DialogActions from '@mui/material/DialogActions';
65
69
  import DialogContent from '@mui/material/DialogContent';
@@ -8508,6 +8512,16 @@ function s(e){const t=window.location.origin,n=n=>{if(n.origin!==t)return;const
8508
8512
 
8509
8513
  function gt(t,e){if(void 0!==document.caretRangeFromPoint){const n=document.caretRangeFromPoint(t,e);return null===n?null:{node:n.startContainer,offset:n.startOffset}}if("undefined"!==document.caretPositionFromPoint){const n=document.caretPositionFromPoint(t,e);return null===n?null:{node:n.offsetNode,offset:n.offset}}return null}const pt="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,ht=pt&&"documentMode"in document?document.documentMode:null,vt=pt&&/Mac|iPod|iPhone|iPad/.test(navigator.platform),Ct=!(!pt||!("InputEvent"in window)||ht)&&"getTargetRanges"in new window.InputEvent("input"),yt=pt&&/Version\/[\d.]+.*Safari/.test(navigator.userAgent),xt=pt&&/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream,Dt=pt&&/^(?=.*Chrome).*/i.test(navigator.userAgent),Nt=pt&&/AppleWebKit\/[\d.]+/.test(navigator.userAgent)&&vt&&!Dt,wt=createCommand("DRAG_DROP_PASTE_FILE");class Et extends ElementNode{static getType(){return "quote"}static clone(t){return new Et(t.__key)}createDOM(t){const e=document.createElement("blockquote");return addClassNamesToElement(e,t.theme.quote),e}updateDOM(t,e){return false}static importDOM(){return {blockquote:t=>({conversion:Ft,priority:0})}}exportDOM(t){const{element:e}=super.exportDOM(t);if(isHTMLElement$1(e)){this.isEmpty()&&e.append(document.createElement("br"));const t=this.getFormatType();t&&(e.style.textAlign=t);const n=this.getDirection();n&&(e.dir=n);}return {element:e}}static importJSON(t){return _t().updateFromJSON(t)}insertNewAfter(t,e){const n=$createParagraphNode(),r=this.getDirection();return n.setDirection(r),this.insertAfter(n,e),n}collapseAtStart(){const t=$createParagraphNode();return this.getChildren().forEach(e=>t.append(e)),this.replace(t),true}canMergeWhenEmpty(){return true}}function _t(){return $applyNodeReplacement(new Et)}class Pt extends ElementNode{__tag;static getType(){return "heading"}static clone(t){return new Pt(t.__tag,t.__key)}constructor(t,e){super(e),this.__tag=t;}getTag(){return this.__tag}setTag(t){const e=this.getWritable();return this.__tag=t,e}createDOM(t){const e=this.__tag,n=document.createElement(e),r=t.theme.heading;if(void 0!==r){const t=r[e];addClassNamesToElement(n,t);}return n}updateDOM(t,e,n){return t.__tag!==this.__tag}static importDOM(){return {h1:t=>({conversion:At,priority:0}),h2:t=>({conversion:At,priority:0}),h3:t=>({conversion:At,priority:0}),h4:t=>({conversion:At,priority:0}),h5:t=>({conversion:At,priority:0}),h6:t=>({conversion:At,priority:0}),p:t=>{const e=t.firstChild;return null!==e&&Tt(e)?{conversion:()=>({node:null}),priority:3}:null},span:t=>Tt(t)?{conversion:t=>({node:St("h1")}),priority:3}:null}}exportDOM(t){const{element:e}=super.exportDOM(t);if(isHTMLElement$1(e)){this.isEmpty()&&e.append(document.createElement("br"));const t=this.getFormatType();t&&(e.style.textAlign=t);const n=this.getDirection();n&&(e.dir=n);}return {element:e}}static importJSON(t){return St(t.tag).updateFromJSON(t)}updateFromJSON(t){return super.updateFromJSON(t).setTag(t.tag)}exportJSON(){return {...super.exportJSON(),tag:this.getTag()}}insertNewAfter(t,e=true){const n=t?t.anchor.offset:0,r=this.getLastDescendant(),o=!r||t&&t.anchor.key===r.getKey()&&n===r.getTextContentSize()||!t?$createParagraphNode():St(this.getTag()),i=this.getDirection();if(o.setDirection(i),this.insertAfter(o,e),0===n&&!this.isEmpty()&&t){const t=$createParagraphNode();t.select(),this.replace(t,true);}return o}collapseAtStart(){const t=this.isEmpty()?$createParagraphNode():St(this.getTag());return this.getChildren().forEach(e=>t.append(e)),this.replace(t),true}extractWithChild(){return true}}function Tt(t){return "span"===t.nodeName.toLowerCase()&&"26pt"===t.style.fontSize}function At(t){const e=t.nodeName.toLowerCase();let n=null;return "h1"!==e&&"h2"!==e&&"h3"!==e&&"h4"!==e&&"h5"!==e&&"h6"!==e||(n=St(e),null!==t.style&&(setNodeIndentFromDOM(t,n),n.setFormat(t.style.textAlign))),{node:n}}function Ft(t){const e=_t();return null!==t.style&&(e.setFormat(t.style.textAlign),setNodeIndentFromDOM(t,e)),{node:e}}function St(t="h1"){return $applyNodeReplacement(new Pt(t))}function Mt(t){let e=null;if(At$2(t,DragEvent)?e=t.dataTransfer:At$2(t,ClipboardEvent)&&(e=t.clipboardData),null===e)return [false,[],false];const n=e.types,r=n.includes("Files"),o=n.includes("text/html")||n.includes("text/plain");return [r,Array.from(e.files),o]}function bt(t){const e=$getSelection();if(!$isRangeSelection(e))return false;const n=new Set,r=e.getNodes();for(let e=0;e<r.length;e++){const o=r[e],i=o.getKey();if(n.has(i))continue;const s=$findMatchingParent(o,t=>$isElementNode(t)&&!t.isInline());if(null===s)continue;const c=s.getKey();s.canIndent()&&!n.has(c)&&(n.add(c),t(s));}return n.size>0}function Kt(t){const e=$getNearestNodeFromDOMNode(t);return $isDecoratorNode(e)}function kt(t){for(const e of ["lowercase","uppercase","capitalize"])t.hasFormat(e)&&t.toggleFormat(e);}function Jt(n){return mergeRegister(n.registerCommand(CLICK_COMMAND,t=>{const e=$getSelection();return !!$isNodeSelection(e)&&(e.clear(),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(DELETE_CHARACTER_COMMAND,t=>{const e=$getSelection();return $isRangeSelection(e)?(e.deleteCharacter(t),true):!!$isNodeSelection(e)&&(e.deleteNodes(),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(DELETE_WORD_COMMAND,t=>{const e=$getSelection();return !!$isRangeSelection(e)&&(e.deleteWord(t),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(DELETE_LINE_COMMAND,t=>{const e=$getSelection();return !!$isRangeSelection(e)&&(e.deleteLine(t),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(CONTROLLED_TEXT_INSERTION_COMMAND,e=>{const r=$getSelection();if("string"==typeof e)null!==r&&r.insertText(e);else {if(null===r)return false;const o=e.dataTransfer;if(null!=o)R(o,r,n);else if($isRangeSelection(r)){const t=e.data;return t&&r.insertText(t),true}}return true},COMMAND_PRIORITY_EDITOR),n.registerCommand(REMOVE_TEXT_COMMAND,()=>{const t=$getSelection();return !!$isRangeSelection(t)&&(t.removeText(),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(FORMAT_TEXT_COMMAND,t=>{const e=$getSelection();return !!$isRangeSelection(e)&&(e.formatText(t),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(FORMAT_ELEMENT_COMMAND,t=>{const e=$getSelection();if(!$isRangeSelection(e)&&!$isNodeSelection(e))return false;const n=e.getNodes();for(const e of n){const n=$findMatchingParent(e,t=>$isElementNode(t)&&!t.isInline());null!==n&&n.setFormat(t);}return true},COMMAND_PRIORITY_EDITOR),n.registerCommand(INSERT_LINE_BREAK_COMMAND,t=>{const e=$getSelection();return !!$isRangeSelection(e)&&(e.insertLineBreak(t),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(INSERT_PARAGRAPH_COMMAND,()=>{const t=$getSelection();return !!$isRangeSelection(t)&&(t.insertParagraph(),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(INSERT_TAB_COMMAND,()=>($insertNodes([$createTabNode()]),true),COMMAND_PRIORITY_EDITOR),n.registerCommand(INDENT_CONTENT_COMMAND,()=>bt(t=>{const e=t.getIndent();t.setIndent(e+1);}),COMMAND_PRIORITY_EDITOR),n.registerCommand(OUTDENT_CONTENT_COMMAND,()=>bt(t=>{const e=t.getIndent();e>0&&t.setIndent(Math.max(0,e-1));}),COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_ARROW_UP_COMMAND,t=>{const e=$getSelection();if($isNodeSelection(e)){const n=e.getNodes();if(n.length>0)return t.preventDefault(),n[0].selectPrevious(),true}else if($isRangeSelection(e)){const n=$getAdjacentNode(e.focus,true);if(!t.shiftKey&&$isDecoratorNode(n)&&!n.isIsolated()&&!n.isInline())return n.selectPrevious(),t.preventDefault(),true}return false},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_ARROW_DOWN_COMMAND,t=>{const e=$getSelection();if($isNodeSelection(e)){const n=e.getNodes();if(n.length>0)return t.preventDefault(),n[0].selectNext(0,0),true}else if($isRangeSelection(e)){if(function(t){const e=t.focus;return "root"===e.key&&e.offset===$getRoot().getChildrenSize()}(e))return t.preventDefault(),true;const n=$getAdjacentNode(e.focus,false);if(!t.shiftKey&&$isDecoratorNode(n)&&!n.isIsolated()&&!n.isInline())return n.selectNext(),t.preventDefault(),true}return false},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_ARROW_LEFT_COMMAND,t=>{const e=$getSelection();if($isNodeSelection(e)){const n=e.getNodes();if(n.length>0)return t.preventDefault(),A$1(n[0])?n[0].selectNext(0,0):n[0].selectPrevious(),true}if(!$isRangeSelection(e))return false;if(Z$1(e,true)){const n=t.shiftKey;return t.preventDefault(),ne(e,n,true),true}return false},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_ARROW_RIGHT_COMMAND,t=>{const e=$getSelection();if($isNodeSelection(e)){const n=e.getNodes();if(n.length>0)return t.preventDefault(),A$1(n[0])?n[0].selectPrevious():n[0].selectNext(0,0),true}if(!$isRangeSelection(e))return false;const n=t.shiftKey;return !!Z$1(e,false)&&(t.preventDefault(),ne(e,n,false),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_BACKSPACE_COMMAND,t=>{if(Kt(t.target))return false;const e=$getSelection();if($isRangeSelection(e)){if(function(t){if(!t.isCollapsed())return false;const{anchor:e}=t;if(0!==e.offset)return false;const n=e.getNode();if($isRootNode(n))return false;const r=yt$1(n);return r.getIndent()>0&&(r.is(n)||n.is(r.getFirstDescendant()))}(e))return t.preventDefault(),n.dispatchCommand(OUTDENT_CONTENT_COMMAND,void 0);if(xt&&"ko-KR"===navigator.language)return false}else if(!$isNodeSelection(e))return false;return t.preventDefault(),n.dispatchCommand(DELETE_CHARACTER_COMMAND,true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_DELETE_COMMAND,t=>{if(Kt(t.target))return false;const e=$getSelection();return !(!$isRangeSelection(e)&&!$isNodeSelection(e))&&(t.preventDefault(),n.dispatchCommand(DELETE_CHARACTER_COMMAND,false))},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_ENTER_COMMAND,t=>{const e=$getSelection();if(!$isRangeSelection(e))return false;if(kt(e),null!==t){if((xt||yt||Nt)&&Ct)return false;if(t.preventDefault(),t.shiftKey)return n.dispatchCommand(INSERT_LINE_BREAK_COMMAND,false)}return n.dispatchCommand(INSERT_PARAGRAPH_COMMAND,void 0)},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_ESCAPE_COMMAND,()=>{const t=$getSelection();return !!$isRangeSelection(t)&&(n.blur(),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(DROP_COMMAND,t=>{const[,e]=Mt(t);if(e.length>0){const r=gt(t.clientX,t.clientY);if(null!==r){const{offset:t,node:o}=r,i=$getNearestNodeFromDOMNode(o);if(null!==i){const e=$createRangeSelection();if($isTextNode(i))e.anchor.set(i.getKey(),t,"text"),e.focus.set(i.getKey(),t,"text");else {const t=i.getParentOrThrow().getKey(),n=i.getIndexWithinParent()+1;e.anchor.set(t,n,"element"),e.focus.set(t,n,"element");}const n=$normalizeSelection__EXPERIMENTAL(e);$setSelection(n);}n.dispatchCommand(wt,e);}return t.preventDefault(),true}const r=$getSelection();return !!$isRangeSelection(r)},COMMAND_PRIORITY_EDITOR),n.registerCommand(DRAGSTART_COMMAND,t=>{const[e]=Mt(t),n=$getSelection();return !(e&&!$isRangeSelection(n))},COMMAND_PRIORITY_EDITOR),n.registerCommand(DRAGOVER_COMMAND,t=>{const[e]=Mt(t),n=$getSelection();if(e&&!$isRangeSelection(n))return false;const r=gt(t.clientX,t.clientY);if(null!==r){const e=$getNearestNodeFromDOMNode(r.node);$isDecoratorNode(e)&&t.preventDefault();}return true},COMMAND_PRIORITY_EDITOR),n.registerCommand(SELECT_ALL_COMMAND,()=>($selectAll(),true),COMMAND_PRIORITY_EDITOR),n.registerCommand(COPY_COMMAND,t=>(F$1(n,At$2(t,ClipboardEvent)?t:null),true),COMMAND_PRIORITY_EDITOR),n.registerCommand(CUT_COMMAND,t=>(async function(t,n){await F$1(n,At$2(t,ClipboardEvent)?t:null),n.update(()=>{const t=$getSelection();$isRangeSelection(t)?t.removeText():$isNodeSelection(t)&&t.getNodes().forEach(t=>t.remove());});}(t,n),true),COMMAND_PRIORITY_EDITOR),n.registerCommand(PASTE_COMMAND,e=>{const[,r,o]=Mt(e);if(r.length>0&&!o)return n.dispatchCommand(wt,r),true;if(isDOMNode(e.target)&&isSelectionCapturedInDecoratorInput(e.target))return false;return null!==$getSelection()&&(function(e,n){e.preventDefault(),n.update(()=>{const r=$getSelection(),o=At$2(e,InputEvent)||At$2(e,KeyboardEvent)?null:e.clipboardData;null!=o&&null!==r&&R(o,r,n);},{tag:PASTE_TAG});}(e,n),true)},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_SPACE_COMMAND,t=>{const e=$getSelection();return $isRangeSelection(e)&&kt(e),false},COMMAND_PRIORITY_EDITOR),n.registerCommand(KEY_TAB_COMMAND,t=>{const e=$getSelection();return $isRangeSelection(e)&&kt(e),false},COMMAND_PRIORITY_EDITOR))}defineExtension({conflictsWith:["@lexical/plain-text"],dependencies:[d],name:"@lexical/rich-text",nodes:()=>[Pt,Et],register:Jt});
8510
8514
 
8515
+ /**
8516
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
8517
+ *
8518
+ * This source code is licensed under the MIT license found in the
8519
+ * LICENSE file in the root directory of this source tree.
8520
+ *
8521
+ */
8522
+
8523
+ class n extends ElementNode{$config(){return this.config("overflow",{$transform(e){e.isEmpty()&&e.remove();},extends:ElementNode})}createDOM(e){const t=document.createElement("span"),r=e.theme.characterLimit;return "string"==typeof r&&(t.className=r),t}updateDOM(e,t){return false}insertNewAfter(e,t=true){return this.getParentOrThrow().insertNewAfter(e,t)}excludeFromCopy(){return true}}defineExtension({name:"@lexical/overflow",nodes:()=>[n]});
8524
+
8511
8525
  const useEditorStyles = makeStyles()((theme, { hasFocus, hasContent, readOnly, hasCustomToolbar }) => ({
8512
8526
  root: {
8513
8527
  position: 'relative',
@@ -8596,7 +8610,7 @@ const useEditorStyles = makeStyles()((theme, { hasFocus, hasContent, readOnly, h
8596
8610
 
8597
8611
  function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
8598
8612
 
8599
- function StyleWrapperPlugin({ showCharcount, helperText, readOnly, classes, label, children, autoFocus, toolbarAnchor, hasCustomToolbar, }) {
8613
+ function StyleWrapperPlugin({ showCharcount, maxChars, helperText, readOnly, classes, label, children, autoFocus, toolbarAnchor, hasCustomToolbar, }) {
8600
8614
  const [editor] = useLexicalComposerContext();
8601
8615
  const [hasFocus, setFocused] = useState(() => {
8602
8616
  return editor.getRootElement() === document.activeElement;
@@ -8644,7 +8658,9 @@ function StyleWrapperPlugin({ showCharcount, helperText, readOnly, classes, labe
8644
8658
  label && (React__default.createElement("label", { className: clsx(styles.label, classes?.label) }, label)),
8645
8659
  React__default.createElement(Box, { className: clsx(styles.editor, classes?.editor) }, children),
8646
8660
  (showCharcount || helperText) && (React__default.createElement(Box, { sx: { margin: '.5rem' } },
8647
- showCharcount && (React__default.createElement(FormHelperText, { className: styles.charcount }, `Antall tegn: ${charCount}`)),
8661
+ showCharcount && (React__default.createElement(FormHelperText, { className: styles.charcount }, maxChars
8662
+ ? `Antall tegn: ${charCount} / ${maxChars}`
8663
+ : `Antall tegn: ${charCount}`)),
8648
8664
  helperText && (React__default.createElement(FormHelperText, { className: styles.helpertext }, helperText))))));
8649
8665
  }
8650
8666
 
@@ -8780,8 +8796,10 @@ var ButtonType;
8780
8796
  (function (ButtonType) {
8781
8797
  ButtonType["bold"] = "bold";
8782
8798
  ButtonType["italic"] = "italic";
8799
+ ButtonType["superscript"] = "superscript";
8800
+ ButtonType["subscript"] = "subscript";
8783
8801
  })(ButtonType || (ButtonType = {}));
8784
- const createButton = (style) => {
8802
+ const createButton = (style = 'bold') => {
8785
8803
  switch (style) {
8786
8804
  case 'bold':
8787
8805
  return {
@@ -8793,6 +8811,16 @@ const createButton = (style) => {
8793
8811
  type: ButtonType[style],
8794
8812
  children: React__default.createElement(FormatItalic, { fontSize: "small" }),
8795
8813
  };
8814
+ case 'superscript':
8815
+ return {
8816
+ type: ButtonType[style],
8817
+ children: React__default.createElement(FormatSuperscript, { fontSize: "small" }),
8818
+ };
8819
+ case 'subscript':
8820
+ return {
8821
+ type: ButtonType[style],
8822
+ children: React__default.createElement(FormatSubscript, { fontSize: "small" }),
8823
+ };
8796
8824
  }
8797
8825
  };
8798
8826
 
@@ -8867,6 +8895,42 @@ function getSelectedNode(selection) {
8867
8895
  }
8868
8896
  }
8869
8897
 
8898
+ var ToolbarActionKind;
8899
+ (function (ToolbarActionKind) {
8900
+ ToolbarActionKind["updateFormat"] = "UPDATE_FORMAT";
8901
+ ToolbarActionKind["updateBoolean"] = "UPDATE_BOOLEAN";
8902
+ ToolbarActionKind["reset"] = "RESET";
8903
+ })(ToolbarActionKind || (ToolbarActionKind = {}));
8904
+ const ToolbarInitialState = {
8905
+ isText: false,
8906
+ format: new Set(),
8907
+ };
8908
+ const modifySet = (set, toModify, add) => {
8909
+ if (add) {
8910
+ return set.add(toModify);
8911
+ }
8912
+ else {
8913
+ set.delete(toModify);
8914
+ return set;
8915
+ }
8916
+ };
8917
+ // This is a local state reducer
8918
+ function ToolbarReducer(state, action) {
8919
+ switch (action.type) {
8920
+ case ToolbarActionKind.reset:
8921
+ return action.payload ? { ...action.payload } : ToolbarInitialState;
8922
+ case ToolbarActionKind.updateBoolean:
8923
+ return { ...state, [action.field]: action.payload };
8924
+ case ToolbarActionKind.updateFormat:
8925
+ return {
8926
+ ...state,
8927
+ format: modifySet(state.format, action.field, action.payload),
8928
+ };
8929
+ default:
8930
+ return state;
8931
+ }
8932
+ }
8933
+
8870
8934
  /**
8871
8935
  * Copyright (c) Meta Platforms, Inc. and affiliates.
8872
8936
  *
@@ -8874,7 +8938,7 @@ function getSelectedNode(selection) {
8874
8938
  * LICENSE file in the root directory of this source tree.
8875
8939
  *
8876
8940
  */
8877
- function TextFormatFloatingToolbar({ editor, anchorElem, isBold, isItalic, buttons, }) {
8941
+ function TextFormatFloatingToolbar({ editor, anchorElem, formats, buttons, }) {
8878
8942
  const { classes } = useButtonStyles();
8879
8943
  const popupCharStylesEditorRef = useRef(null);
8880
8944
  function mouseMoveListener(e) {
@@ -8963,14 +9027,12 @@ function TextFormatFloatingToolbar({ editor, anchorElem, isBold, isItalic, butto
8963
9027
  top: 0,
8964
9028
  left: 0,
8965
9029
  zIndex: 1,
8966
- } }, buttons?.map(({ type, children }, key) => (React.createElement(ToggleButton, { classes: { root: classes.btn, selected: classes.btnSelected }, value: type, selected: type === 'italic' ? isItalic : isBold, size: "small", key: key, onClick: () => {
9030
+ } }, buttons?.map(({ type, children }) => (React.createElement(ToggleButton, { classes: { root: classes.btn, selected: classes.btnSelected }, value: type, selected: formats.has(type), size: "small", key: type, onClick: () => {
8967
9031
  editor.dispatchCommand(FORMAT_TEXT_COMMAND, type);
8968
9032
  }, "aria-label": `format text as ${type.toLowerCase}` }, children)))))));
8969
9033
  }
8970
9034
  function useFloatingTextFormatToolbar(editor, anchorElem, buttons, CustomToolbar) {
8971
- const [isText, setIsText] = useState(false);
8972
- const [isBold, setIsBold] = useState(false);
8973
- const [isItalic, setIsItalic] = useState(false);
9035
+ const [state, dispatch] = React.useReducer(ToolbarReducer, ToolbarInitialState);
8974
9036
  const updatePopup = useCallback(() => {
8975
9037
  editor.getEditorState().read(() => {
8976
9038
  // Should not pop up the floating toolbar when using IME input
@@ -8984,7 +9046,11 @@ function useFloatingTextFormatToolbar(editor, anchorElem, buttons, CustomToolbar
8984
9046
  (!$isRangeSelection(selection) ||
8985
9047
  rootElement === null ||
8986
9048
  !rootElement.contains(nativeSelection.anchorNode))) {
8987
- setIsText(false);
9049
+ dispatch({
9050
+ type: ToolbarActionKind.updateBoolean,
9051
+ field: 'isText',
9052
+ payload: false,
9053
+ });
8988
9054
  return;
8989
9055
  }
8990
9056
  if (!$isRangeSelection(selection)) {
@@ -8992,17 +9058,47 @@ function useFloatingTextFormatToolbar(editor, anchorElem, buttons, CustomToolbar
8992
9058
  }
8993
9059
  const node = getSelectedNode(selection);
8994
9060
  // Update text format
8995
- setIsBold(selection.hasFormat('bold'));
8996
- setIsItalic(selection.hasFormat('italic'));
9061
+ dispatch({
9062
+ type: ToolbarActionKind.updateFormat,
9063
+ field: 'bold',
9064
+ payload: selection.hasFormat('bold'),
9065
+ });
9066
+ dispatch({
9067
+ type: ToolbarActionKind.updateFormat,
9068
+ field: 'italic',
9069
+ payload: selection.hasFormat('italic'),
9070
+ });
9071
+ dispatch({
9072
+ type: ToolbarActionKind.updateFormat,
9073
+ field: 'superscript',
9074
+ payload: selection.hasFormat('superscript'),
9075
+ });
9076
+ dispatch({
9077
+ type: ToolbarActionKind.updateFormat,
9078
+ field: 'subscript',
9079
+ payload: selection.hasFormat('subscript'),
9080
+ });
8997
9081
  if (selection.getTextContent() !== '') {
8998
- setIsText($isTextNode(node) || $isParagraphNode(node));
9082
+ dispatch({
9083
+ type: ToolbarActionKind.updateBoolean,
9084
+ field: 'isText',
9085
+ payload: $isTextNode(node) || $isParagraphNode(node),
9086
+ });
8999
9087
  }
9000
9088
  else {
9001
- setIsText(false);
9089
+ dispatch({
9090
+ type: ToolbarActionKind.updateBoolean,
9091
+ field: 'isText',
9092
+ payload: false,
9093
+ });
9002
9094
  }
9003
9095
  const rawTextContent = selection.getTextContent().replace(/\n/g, '');
9004
9096
  if (!selection.isCollapsed() && rawTextContent === '') {
9005
- setIsText(false);
9097
+ dispatch({
9098
+ type: ToolbarActionKind.updateBoolean,
9099
+ field: 'isText',
9100
+ payload: false,
9101
+ });
9006
9102
  return;
9007
9103
  }
9008
9104
  });
@@ -9018,7 +9114,11 @@ function useFloatingTextFormatToolbar(editor, anchorElem, buttons, CustomToolbar
9018
9114
  updatePopup();
9019
9115
  }), editor.registerRootListener(() => {
9020
9116
  if (editor.getRootElement() === null) {
9021
- setIsText(false);
9117
+ dispatch({
9118
+ type: ToolbarActionKind.updateBoolean,
9119
+ field: 'isText',
9120
+ payload: false,
9121
+ });
9022
9122
  }
9023
9123
  }));
9024
9124
  }, [editor, updatePopup]);
@@ -9029,12 +9129,12 @@ function useFloatingTextFormatToolbar(editor, anchorElem, buttons, CustomToolbar
9029
9129
  left: '1em',
9030
9130
  zIndex: 1,
9031
9131
  } },
9032
- React.createElement(CustomToolbar, { buttons: buttons, editor: editor, isSelected: [isBold, isItalic] })), anchorElem);
9132
+ React.createElement(CustomToolbar, { buttons: buttons, editor: editor, formats: state.format })), anchorElem);
9033
9133
  }
9034
- if (!isText) {
9134
+ if (!state.isText) {
9035
9135
  return null;
9036
9136
  }
9037
- return createPortal(React.createElement(TextFormatFloatingToolbar, { editor: editor, anchorElem: anchorElem, isBold: isBold, isItalic: isItalic, buttons: buttons }), anchorElem);
9137
+ return createPortal(React.createElement(TextFormatFloatingToolbar, { editor: editor, anchorElem: anchorElem, formats: state.format, buttons: buttons }), anchorElem);
9038
9138
  }
9039
9139
  function FloatingTextFormatToolbarPlugin({ anchorElem, buttons, CustomToolbar, }) {
9040
9140
  const [editor] = useLexicalComposerContext();
@@ -9087,126 +9187,159 @@ function HeadingPlugin({ html }) {
9087
9187
  return null;
9088
9188
  }
9089
9189
 
9090
- const allowBoldItalic = (node) => {
9091
- if (node.hasFormat('italic') &&
9092
- node.hasFormat('bold') &&
9093
- (node.hasFormat('code') ||
9094
- node.hasFormat('highlight') ||
9095
- node.hasFormat('strikethrough') ||
9096
- node.hasFormat('subscript') ||
9097
- node.hasFormat('superscript') ||
9098
- node.hasFormat('underline'))) {
9099
- node.setFormat(0); // setFormat only sets one specific format. Therefore toggle is used to have both applied.
9100
- node.toggleFormat('bold');
9101
- node.toggleFormat('italic');
9190
+ const RESTRICTED_FORMATS = [
9191
+ 'code',
9192
+ 'highlight',
9193
+ 'strikethrough',
9194
+ 'underline',
9195
+ ];
9196
+ const hasAnyFormat = (node, formats) => {
9197
+ return formats.some((format) => node.hasFormat(format));
9198
+ };
9199
+ const applyAllowedFormats = (node, allowedFormats) => {
9200
+ const hasBold = node.hasFormat('bold');
9201
+ const hasItalic = node.hasFormat('italic');
9202
+ const hasSuperscript = node.hasFormat('superscript');
9203
+ const hasSubscript = node.hasFormat('subscript');
9204
+ const keepBold = allowedFormats.includes('bold') && hasBold;
9205
+ const keepItalic = allowedFormats.includes('italic') && hasItalic;
9206
+ const keepSuperscript = allowedFormats.includes('superscript') && hasSuperscript;
9207
+ const keepSubscript = allowedFormats.includes('subscript') && hasSubscript;
9208
+ if (!keepBold && !keepItalic && !keepSuperscript && !keepSubscript) {
9209
+ return;
9102
9210
  }
9103
- else if (node.hasFormat('italic') && node.hasFormat('bold')) {
9104
- return; // Need to set as italic to ensure format is only italic.
9105
- }
9106
- else if (node.hasFormat('bold') &&
9107
- (node.hasFormat('code') ||
9108
- node.hasFormat('highlight') ||
9109
- node.hasFormat('strikethrough') ||
9110
- node.hasFormat('subscript') ||
9111
- node.hasFormat('superscript') ||
9112
- node.hasFormat('underline'))) {
9113
- node.setFormat('bold');
9114
- }
9115
- else if (node.hasFormat('italic') &&
9116
- (node.hasFormat('code') ||
9117
- node.hasFormat('highlight') ||
9118
- node.hasFormat('strikethrough') ||
9119
- node.hasFormat('subscript') ||
9120
- node.hasFormat('superscript') ||
9121
- node.hasFormat('underline'))) {
9122
- node.setFormat('italic');
9123
- }
9124
- else if (node.hasFormat('code') ||
9125
- node.hasFormat('highlight') ||
9126
- node.hasFormat('strikethrough') ||
9127
- node.hasFormat('subscript') ||
9128
- node.hasFormat('superscript') ||
9129
- node.hasFormat('underline')) {
9130
- node.setFormat(0); // Sets format to none.
9211
+ const hasDisallowedFormatting = hasAnyFormat(node, RESTRICTED_FORMATS);
9212
+ if (!hasDisallowedFormatting) {
9213
+ if (keepBold || keepItalic || keepSuperscript || keepSubscript) {
9214
+ return;
9215
+ }
9131
9216
  }
9132
- };
9133
- const allowBold = (node) => {
9134
- if (node.hasFormat('bold') &&
9135
- (node.hasFormat('code') ||
9136
- node.hasFormat('highlight') ||
9137
- node.hasFormat('strikethrough') ||
9138
- node.hasFormat('subscript') ||
9139
- node.hasFormat('superscript') ||
9140
- node.hasFormat('underline'))) {
9141
- node.setFormat('bold');
9142
- }
9143
- else if (node.hasFormat('italic') ||
9144
- node.hasFormat('code') ||
9145
- node.hasFormat('highlight') ||
9146
- node.hasFormat('strikethrough') ||
9147
- node.hasFormat('subscript') ||
9148
- node.hasFormat('superscript') ||
9149
- node.hasFormat('underline')) {
9150
- node.setFormat(0); // Sets format to none.
9217
+ if (keepBold) {
9218
+ node.toggleFormat('bold');
9151
9219
  }
9152
- };
9153
- const allowItalic = (node) => {
9154
- if (node.hasFormat('italic') &&
9155
- (node.hasFormat('code') ||
9156
- node.hasFormat('highlight') ||
9157
- node.hasFormat('strikethrough') ||
9158
- node.hasFormat('subscript') ||
9159
- node.hasFormat('superscript') ||
9160
- node.hasFormat('underline'))) {
9161
- node.setFormat('italic');
9162
- }
9163
- else if (node.hasFormat('bold') ||
9164
- node.hasFormat('code') ||
9165
- node.hasFormat('highlight') ||
9166
- node.hasFormat('strikethrough') ||
9167
- node.hasFormat('subscript') ||
9168
- node.hasFormat('superscript') ||
9169
- node.hasFormat('underline')) {
9170
- node.setFormat(0); // Sets format to none.
9220
+ if (keepItalic) {
9221
+ node.toggleFormat('italic');
9171
9222
  }
9172
- };
9173
- const disallowAll = (node) => {
9174
- if (node.hasFormat('bold') ||
9175
- node.hasFormat('italic') ||
9176
- node.hasFormat('code') ||
9177
- node.hasFormat('highlight') ||
9178
- node.hasFormat('strikethrough') ||
9179
- node.hasFormat('subscript') ||
9180
- node.hasFormat('superscript') ||
9181
- node.hasFormat('underline')) {
9182
- node.setFormat(0); // Sets format to none.
9223
+ if (keepSuperscript) {
9224
+ node.toggleFormat('superscript');
9225
+ }
9226
+ if (keepSubscript) {
9227
+ node.toggleFormat('subscript');
9183
9228
  }
9184
9229
  };
9185
9230
  function TextNodeStylingPlugin({ allowedStyles, }) {
9186
9231
  const [editor] = useLexicalComposerContext();
9187
9232
  useEffect(() => {
9188
9233
  return editor.registerNodeTransform(TextNode, (node) => {
9234
+ const allowedFormats = allowedStyles ?? [];
9189
9235
  if (allowedStyles === undefined) {
9190
- allowBoldItalic(node);
9236
+ allowedFormats.push('bold', 'italic', 'superscript', 'subscript');
9191
9237
  }
9192
- else if (allowedStyles.includes(ButtonType.bold) &&
9193
- allowedStyles.includes(ButtonType.italic)) {
9194
- allowBoldItalic(node);
9195
- }
9196
- else if (allowedStyles.includes(ButtonType.bold)) {
9197
- allowBold(node);
9198
- }
9199
- else if (allowedStyles.includes(ButtonType.italic)) {
9200
- allowItalic(node);
9201
- }
9202
- else {
9203
- disallowAll(node);
9238
+ applyAllowedFormats(node, allowedFormats);
9239
+ });
9240
+ }, [editor, allowedStyles]);
9241
+ return null;
9242
+ }
9243
+
9244
+ function ReadModePlugin({ readOnly }) {
9245
+ const [editor] = useLexicalComposerContext();
9246
+ useEffect(() => {
9247
+ editor.setEditable(readOnly ?? true);
9248
+ }, [editor, readOnly]);
9249
+ return null;
9250
+ }
9251
+
9252
+ //** This works together with the characterLimitPlugin from lexical.
9253
+ // Lexical's plugin marks the overflowing characters as overflowNodes, and this plugin removes them. */
9254
+ function RemoveOverflowPlugin({ maxChars }) {
9255
+ const [editor] = useLexicalComposerContext();
9256
+ useEffect(() => {
9257
+ editor.registerTextContentListener((content) => {
9258
+ // For some reason a newline "Enter" inserts two \n characters.
9259
+ if (maxChars) {
9260
+ const count = content.replaceAll('\n\n', '\n').length;
9261
+ if (count > maxChars) {
9262
+ mergeRegister(editor.registerNodeTransform(n, (node) => {
9263
+ node.remove();
9264
+ }));
9265
+ }
9204
9266
  }
9205
9267
  });
9206
- }, [editor]);
9268
+ }, [editor, maxChars]);
9207
9269
  return null;
9208
9270
  }
9209
9271
 
9272
+ const PLACEHOLDER_CLASS_NAME = 'lexicalEditor-placeholder';
9273
+ const getAllLexicalChildren = (editor) => {
9274
+ const childrenKeys = editor
9275
+ .getEditorState()
9276
+ .read(() => $getRoot().getChildrenKeys());
9277
+ return childrenKeys.map((key) => ({
9278
+ key: key,
9279
+ node: $getNodeByKey(key),
9280
+ htmlElement: editor.getElementByKey(key),
9281
+ }));
9282
+ };
9283
+ const setPlaceholderOnSelection = ({ selection, editor, placeholder, }) => {
9284
+ /**
9285
+ * 1. Get all lexical nodes as HTML elements
9286
+ */
9287
+ const children = getAllLexicalChildren(editor);
9288
+ /**
9289
+ * 2. Remove "placeholder" class if it was added before
9290
+ */
9291
+ children.forEach(({ htmlElement }) => {
9292
+ if (!htmlElement) {
9293
+ return;
9294
+ }
9295
+ const classList = htmlElement.classList;
9296
+ if (classList.length && classList.contains(PLACEHOLDER_CLASS_NAME)) {
9297
+ classList.remove(PLACEHOLDER_CLASS_NAME);
9298
+ }
9299
+ });
9300
+ /**
9301
+ * 3. Do nothing if there is more than one lexical child,
9302
+ * since we only apply one placeholder in total.
9303
+ */
9304
+ if (children.length > 1) {
9305
+ return;
9306
+ }
9307
+ /**
9308
+ * 4. Get "PointType" object, that contain Nodes data
9309
+ */
9310
+ const anchor = selection.anchor;
9311
+ placeholder = DOMPurify.sanitize(placeholder?.replace(/<[^>]+>/g, ''));
9312
+ if (placeholder) {
9313
+ const selectedHtmlElement = editor.getElementByKey(anchor.key);
9314
+ selectedHtmlElement?.classList.add(PLACEHOLDER_CLASS_NAME);
9315
+ selectedHtmlElement?.setAttribute('data-placeholder', placeholder);
9316
+ }
9317
+ };
9318
+ const setNodePlaceholderFromSelection = (editor, placeholder) => {
9319
+ editor.getEditorState().read(() => {
9320
+ const selection = $getSelection();
9321
+ if (!$isRangeSelection(selection)) {
9322
+ // Do nothing if user selected node's content
9323
+ return;
9324
+ }
9325
+ setPlaceholderOnSelection({ selection, editor, placeholder });
9326
+ });
9327
+ };
9328
+ const AddPlaceholderPlugin = ({ placeholder, }) => {
9329
+ const [editor] = useLexicalComposerContext();
9330
+ useEffect(() => {
9331
+ if (placeholder) {
9332
+ return editor.registerUpdateListener(() => {
9333
+ setNodePlaceholderFromSelection(editor, placeholder ?? '');
9334
+ });
9335
+ }
9336
+ else {
9337
+ return;
9338
+ }
9339
+ }, [editor, placeholder]);
9340
+ return null;
9341
+ };
9342
+
9210
9343
  // Classes here are added to the relevant tags i.e.(<strong>)
9211
9344
  const theme = {
9212
9345
  text: {
@@ -9220,16 +9353,18 @@ function onError(error) {
9220
9353
  const createDefaultButtons = () => [
9221
9354
  createButton('bold'),
9222
9355
  createButton('italic'),
9356
+ createButton('superscript'),
9357
+ createButton('subscript'),
9223
9358
  ];
9224
9359
  /* This allows interaction with the editor outside of the LexicalComposer */
9225
9360
  // export const editorRef = useRef<LexicalEditor>(null);
9226
- function Editor({ html, label, classes, autoFocus, helperText, showCharCount, allowedStyles, blockPasting, disableNewlines, onContentChange, editorRef, stripPastedStyles, readOnly, Toolbar, }) {
9361
+ function Editor({ html, label, classes, autoFocus, helperText, showCharCount, allowedStyles, blockPasting, disableNewlines, onContentChange, editorRef, stripPastedStyles, readOnly, Toolbar, maxChars, placeholder, }) {
9227
9362
  const initialConfig = {
9228
9363
  namespace: 'GrepEditor',
9229
9364
  theme,
9230
9365
  editable: !readOnly,
9231
9366
  onError,
9232
- nodes: [Pt],
9367
+ nodes: [Pt, n],
9233
9368
  html: {
9234
9369
  export: htmlExportMap,
9235
9370
  },
@@ -9248,7 +9383,7 @@ function Editor({ html, label, classes, autoFocus, helperText, showCharCount, al
9248
9383
  : allowedStyles.map(createButton);
9249
9384
  return (React__default.createElement(LexicalComposer, { initialConfig: initialConfig },
9250
9385
  React__default.createElement(EditorRefPlugin, { editorRef: editorRef }),
9251
- React__default.createElement(StyleWrapperPlugin, { helperText: helperText, showCharcount: showCharCount, readOnly: readOnly, classes: classes, label: label, autoFocus: autoFocus, toolbarAnchor: onRef, hasCustomToolbar: Toolbar !== undefined },
9386
+ React__default.createElement(StyleWrapperPlugin, { helperText: helperText, showCharcount: showCharCount, maxChars: maxChars, readOnly: readOnly, classes: classes, label: label, autoFocus: autoFocus, toolbarAnchor: onRef, hasCustomToolbar: Toolbar !== undefined },
9252
9387
  canStyle && floatingAnchorElem && (React__default.createElement(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem, buttons: buttons, CustomToolbar: Toolbar })),
9253
9388
  React__default.createElement(RichTextPlugin, { contentEditable: React__default.createElement(ContentEditable, { spellCheck: false, className: "GrepEditor", style: { outline: 'none' } }), placeholder: null, ErrorBoundary: LexicalErrorBoundary }),
9254
9389
  React__default.createElement(HistoryPlugin, null),
@@ -9257,7 +9392,12 @@ function Editor({ html, label, classes, autoFocus, helperText, showCharCount, al
9257
9392
  React__default.createElement(HeadingPlugin, { html: html }),
9258
9393
  React__default.createElement(ModifyPastePlugin, { blockPasting: blockPasting, stripPastedStyles: stripPastedStyles }),
9259
9394
  React__default.createElement(PreventNewlinesPlugin, { disableNewlines: disableNewlines }),
9260
- React__default.createElement(TextNodeStylingPlugin, { allowedStyles: allowedStyles }))));
9395
+ React__default.createElement(TextNodeStylingPlugin, { allowedStyles: allowedStyles }),
9396
+ React__default.createElement(ReadModePlugin, { readOnly: !readOnly }),
9397
+ maxChars && (React__default.createElement(React__default.Fragment, null,
9398
+ React__default.createElement(RemoveOverflowPlugin, { maxChars: maxChars }),
9399
+ React__default.createElement(CharacterLimitPlugin, { charset: "UTF-16", maxLength: maxChars, renderer: () => React__default.createElement(React__default.Fragment, null) })))),
9400
+ React__default.createElement(AddPlaceholderPlugin, { placeholder: placeholder })));
9261
9401
  }
9262
9402
 
9263
9403
  /* To have both italic and bold styles apply, css rules need to be added as per: https://lexical.dev/docs/getting-started/theming */