@pie-lib/editable-html-tip-tap 1.0.0 → 1.0.2

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/src/index.jsx CHANGED
@@ -27,6 +27,7 @@ import { color } from '@pie-lib/render-ui';
27
27
  import { primary } from './theme';
28
28
  import { PIE_TOOLBAR__CLASS } from './constants';
29
29
  import { DoneButton } from './plugins/toolbar/done-button';
30
+ import { buildPlugins, DEFAULT_PLUGINS } from "./plugins/index";
30
31
  import Bold from '@material-ui/icons/FormatBold';
31
32
  import Italic from '@material-ui/icons/FormatItalic';
32
33
  import Strikethrough from '@material-ui/icons/FormatStrikethrough';
@@ -40,8 +41,8 @@ import ImageIcon from '@material-ui/icons/Image';
40
41
  import { ToolbarIcon } from './plugins/respArea/icons';
41
42
  import Redo from '@material-ui/icons/Redo';
42
43
  import Undo from '@material-ui/icons/Undo';
43
- import TheatersIcon from "@material-ui/icons/Theaters";
44
- import VolumeUpIcon from "@material-ui/icons/VolumeUp";
44
+ import TheatersIcon from '@material-ui/icons/Theaters';
45
+ import VolumeUpIcon from '@material-ui/icons/VolumeUp';
45
46
  import { characterIcons, spanishConfig, specialConfig } from './plugins/characters/utils';
46
47
  import PropTypes from 'prop-types';
47
48
  import { MathToolbar, PureToolbar } from '@pie-lib/math-toolbar';
@@ -52,7 +53,9 @@ import CSSIcon from './plugins/css/icons';
52
53
 
53
54
  import { ImageUploadNode } from './extensions/image';
54
55
  import { Media } from './extensions/media';
55
- import { CSSMark } from "./extensions/css";
56
+ import { CSSMark } from './extensions/css';
57
+ import { AddColumn, AddRow, RemoveColumn, RemoveRow, RemoveTable } from './plugins/table/icons';
58
+ import BorderAll from '@material-ui/icons/BorderAll';
56
59
 
57
60
  const CharacterIcon = ({ letter }) => (
58
61
  <div
@@ -248,15 +251,24 @@ const HeadingIcon = () => (
248
251
  );
249
252
 
250
253
  const ExtendedTable = Table.extend({
254
+ addAttributes() {
255
+ return {
256
+ border: { default: '1' },
257
+ };
258
+ },
251
259
  renderHTML(props) {
252
260
  const originalTable = this.parent(props);
261
+ const { border } = props.HTMLAttributes;
262
+
263
+ const previousStyle = `${originalTable[1].style}${originalTable[1].style.match(/.*; */) ? '' : ';'}`;
253
264
 
254
- originalTable[1].style = `${originalTable[1].style} width: 100%;
265
+ originalTable[1].style = `${previousStyle}
266
+ width: 100%;
255
267
  color: var(--pie-text, black);
256
268
  table-layout: fixed;
257
269
  border-collapse: collapse;
258
270
  background-color: var(--pie-background, rgba(255, 255, 255))`;
259
- originalTable[1].border = '1';
271
+ originalTable[1].border = border ? border : '1';
260
272
 
261
273
  return originalTable;
262
274
  },
@@ -353,6 +365,24 @@ const styles = (theme) => ({
353
365
  borderTop: '1px solid var(--gray-2)',
354
366
  margin: '2rem 0',
355
367
  },
368
+
369
+ '& table': {
370
+ tableLayout: 'fixed',
371
+ width: '100%',
372
+ borderCollapse: 'collapse',
373
+ color: color.text(),
374
+ backgroundColor: color.background(),
375
+ },
376
+ '& table:not([border="1"]) tr': {
377
+ borderTop: '1px solid #dfe2e5',
378
+ },
379
+ '& td, th': {
380
+ padding: '.6em 1em',
381
+ textAlign: 'center',
382
+ },
383
+ '& table:not([border="1"]) td, th': {
384
+ border: '1px solid #dfe2e5',
385
+ },
356
386
  },
357
387
  children: {
358
388
  padding: '10px 16px',
@@ -511,6 +541,7 @@ function TiptapContainer(props) {
511
541
  children,
512
542
  disableUnderline,
513
543
  disableScrollbar,
544
+ activePlugins,
514
545
  toolbarOpts,
515
546
  responseAreaProps,
516
547
  autoFocus,
@@ -579,6 +610,7 @@ function TiptapContainer(props) {
579
610
  editor={editor}
580
611
  responseAreaProps={responseAreaProps}
581
612
  toolbarOpts={toolbarOpts}
613
+ activePlugins={activePlugins}
582
614
  onChange={props.onChange}
583
615
  />
584
616
  )}
@@ -588,7 +620,7 @@ function TiptapContainer(props) {
588
620
 
589
621
  const EditorContainer = withStyles(styles)(TiptapContainer);
590
622
 
591
- function MenuBar({ editor, classes, toolbarOpts: toolOpts, responseAreaProps, onChange }) {
623
+ function MenuBar({ editor, classes, activePlugins, toolbarOpts: toolOpts, responseAreaProps, onChange }) {
592
624
  const [showPicker, setShowPicker] = useState(false);
593
625
  const toolbarOpts = toolOpts ?? {};
594
626
  // Read the current editor's state, and re-render the component when it changes
@@ -603,14 +635,14 @@ function MenuBar({ editor, classes, toolbarOpts: toolOpts, responseAreaProps, on
603
635
  currentNode = selection.node; // the selected node
604
636
  }
605
637
 
606
- const customToolbarActive =
638
+ const hideDefaultToolbar =
607
639
  ctx.editor?.isActive('math') ||
608
640
  ctx.editor?.isActive('explicit_constructed_response') ||
609
641
  ctx.editor?.isActive('imageUploadNode');
610
642
 
611
643
  return {
612
644
  currentNode,
613
- customToolbarActive,
645
+ hideDefaultToolbar,
614
646
  isFocused: ctx.editor?.isFocused,
615
647
  isBold: ctx.editor.isActive('bold') ?? false,
616
648
  canBold:
@@ -620,6 +652,7 @@ function MenuBar({ editor, classes, toolbarOpts: toolOpts, responseAreaProps, on
620
652
  .toggleBold()
621
653
  .run() ?? false,
622
654
  isTable: ctx.editor.isActive('table') ?? false,
655
+ tableHasBorder: ctx.editor.getAttributes('table')?.border === '1' ?? false,
623
656
  canTable:
624
657
  ctx.editor
625
658
  .can()
@@ -698,414 +731,336 @@ function MenuBar({ editor, classes, toolbarOpts: toolOpts, responseAreaProps, on
698
731
  const handleMouseDown = (e) => {
699
732
  e.preventDefault();
700
733
  };
734
+ const toolbarButtons = useMemo(
735
+ () => [
736
+ {
737
+ icon: <GridOn />,
738
+ onClick: (editor) =>
739
+ editor
740
+ .chain()
741
+ .focus()
742
+ .insertTable({ rows: 2, cols: 2, withHeaderRow: false })
743
+ .run(),
744
+ hidden: (state) => !activePlugins?.includes('table') || state.isTable,
745
+ isActive: (state) => state.isTable,
746
+ isDisabled: (state) => !state.canTable,
747
+ },
748
+ {
749
+ icon: <AddRow />,
750
+ onClick: (editor) =>
751
+ editor
752
+ .chain()
753
+ .focus()
754
+ .addRowAfter()
755
+ .run(),
756
+ hidden: (state) => !state.isTable,
757
+ isActive: (state) => state.isTable,
758
+ isDisabled: (state) => !state.canTable,
759
+ },
760
+ {
761
+ icon: <RemoveRow />,
762
+ onClick: (editor) =>
763
+ editor
764
+ .chain()
765
+ .focus()
766
+ .deleteRow()
767
+ .run(),
768
+ hidden: (state) => !state.isTable,
769
+ isActive: (state) => state.isTable,
770
+ isDisabled: (state) => !state.canTable,
771
+ },
772
+ {
773
+ icon: <AddColumn />,
774
+ onClick: (editor) =>
775
+ editor
776
+ .chain()
777
+ .focus()
778
+ .addColumnAfter()
779
+ .run(),
780
+ hidden: (state) => !state.isTable,
781
+ isActive: (state) => state.isTable,
782
+ isDisabled: (state) => !state.canTable,
783
+ },
784
+ {
785
+ icon: <RemoveColumn />,
786
+ onClick: (editor) =>
787
+ editor
788
+ .chain()
789
+ .focus()
790
+ .deleteColumn()
791
+ .run(),
792
+ hidden: (state) => !state.isTable,
793
+ isActive: (state) => state.isTable,
794
+ isDisabled: (state) => !state.canTable,
795
+ },
796
+ {
797
+ icon: <RemoveTable />,
798
+ onClick: (editor) =>
799
+ editor
800
+ .chain()
801
+ .focus()
802
+ .deleteTable()
803
+ .run(),
804
+ hidden: (state) => !state.isTable,
805
+ isActive: (state) => state.isTable,
806
+ isDisabled: (state) => !state.canTable,
807
+ },
808
+ {
809
+ icon: <BorderAll />,
810
+ onClick: (editor) => {
811
+ const tableAttrs = editor.getAttributes('table');
812
+
813
+ const update = {
814
+ ...tableAttrs,
815
+ border: tableAttrs.border !== '0' ? '0' : '1',
816
+ };
817
+
818
+ editor.commands.updateAttributes('table', update);
819
+ },
820
+ hidden: (state) => !state.isTable,
821
+ isActive: (state) => state.tableHasBorder,
822
+ isDisabled: (state) => !state.canTable,
823
+ },
824
+ {
825
+ icon: <Bold />,
826
+ onClick: (editor) =>
827
+ editor
828
+ .chain()
829
+ .focus()
830
+ .toggleBold()
831
+ .run(),
832
+ hidden: (state) => !activePlugins?.includes('bold') || state.isTable,
833
+ isActive: (state) => state.isBold,
834
+ isDisabled: (state) => !state.canBold,
835
+ },
836
+ {
837
+ icon: <Italic />,
838
+ onClick: (editor) =>
839
+ editor
840
+ .chain()
841
+ .focus()
842
+ .toggleItalic()
843
+ .run(),
844
+ hidden: (state) => !activePlugins?.includes('italic') || state.isTable,
845
+ isActive: (state) => state.isItalic,
846
+ isDisabled: (state) => !state.canItalic,
847
+ },
848
+ {
849
+ icon: <Strikethrough />,
850
+ onClick: (editor) =>
851
+ editor
852
+ .chain()
853
+ .focus()
854
+ .toggleStrike()
855
+ .run(),
856
+ hidden: (state) => !activePlugins?.includes('strikethrough') || state.isTable,
857
+ isActive: (state) => state.isStrike,
858
+ isDisabled: (state) => !state.canStrike,
859
+ },
860
+ {
861
+ icon: <Code />,
862
+ onClick: (editor) =>
863
+ editor
864
+ .chain()
865
+ .focus()
866
+ .toggleCode()
867
+ .run(),
868
+ hidden: (state) => !activePlugins?.includes('code') || state.isTable,
869
+ isActive: (state) => state.isCode,
870
+ isDisabled: (state) => !state.canCode,
871
+ },
872
+ {
873
+ icon: <Underline />,
874
+ onClick: (editor) =>
875
+ editor
876
+ .chain()
877
+ .focus()
878
+ .toggleUnderline()
879
+ .run(),
880
+ hidden: (state) => !activePlugins?.includes('underline') || state.isTable,
881
+ isActive: (state) => state.isUnderline,
882
+ },
883
+ {
884
+ icon: <SubscriptIcon />,
885
+ onClick: (editor) =>
886
+ editor
887
+ .chain()
888
+ .focus()
889
+ .toggleSubscript()
890
+ .run(),
891
+ hidden: (state) => !activePlugins?.includes('subscript') || state.isTable,
892
+ isActive: (state) => state.isSubScript,
893
+ },
894
+ {
895
+ icon: <SuperscriptIcon />,
896
+ onClick: (editor) =>
897
+ editor
898
+ .chain()
899
+ .focus()
900
+ .toggleSuperscript()
901
+ .run(),
902
+ hidden: (state) => !activePlugins?.includes('superscript') || state.isTable,
903
+ isActive: (state) => state.isSuperScript,
904
+ },
905
+ {
906
+ icon: <ImageIcon />,
907
+ hidden: (state) => !activePlugins?.includes('image') || state.isTable,
908
+ onClick: (editor) =>
909
+ editor
910
+ .chain()
911
+ .focus()
912
+ .setImageUploadNode()
913
+ .run(),
914
+ },
915
+ {
916
+ icon: <TheatersIcon />,
917
+ hidden: (state) => !activePlugins?.includes('video') || state.isTable,
918
+ onClick: (editor) =>
919
+ editor
920
+ .chain()
921
+ .focus()
922
+ .insertMedia({ tag: 'video' })
923
+ .run(),
924
+ },
925
+ {
926
+ icon: <VolumeUpIcon />,
927
+ hidden: (state) => !activePlugins?.includes('audio') || state.isTable,
928
+ onClick: (editor) =>
929
+ editor
930
+ .chain()
931
+ .focus()
932
+ .insertMedia({ tag: 'audio' })
933
+ .run(),
934
+ },
935
+ {
936
+ icon: <CSSIcon />,
937
+ hidden: (state) => !activePlugins?.includes('css') || state.isTable,
938
+ onClick: (editor) => editor.commands.openCSSClassDialog(),
939
+ },
940
+ {
941
+ icon: <HeadingIcon />,
942
+ hidden: (state) => !activePlugins?.includes('h3') || state.isTable,
943
+ onClick: (editor) =>
944
+ editor
945
+ .chain()
946
+ .focus()
947
+ .toggleHeading({ level: 3 })
948
+ .run(),
949
+ isActive: (state) => state.isHeading3,
950
+ },
951
+ {
952
+ icon: <Functions />,
953
+ hidden: () => !activePlugins?.includes('math'),
954
+ onClick: (editor) =>
955
+ editor
956
+ .chain()
957
+ .focus()
958
+ .insertMath('')
959
+ .run(),
960
+ },
961
+ {
962
+ icon: <CharacterIcon letter="ñ" />,
963
+ hidden: (state) => !activePlugins?.includes('languageCharacters') || state.isTable,
964
+ onClick: () => setShowPicker(spanishConfig),
965
+ },
966
+ {
967
+ icon: <CharacterIcon letter="€" />,
968
+ hidden: (state) => activePlugins?.filter(p => p === 'languageCharacters').length !== 2 || state.isTable,
969
+ onClick: () => setShowPicker(specialConfig),
970
+ },
971
+ {
972
+ icon: <TextAlignIcon editor={editor} />,
973
+ hidden: (state) => !activePlugins?.includes('text-align') || state.isTable,
974
+ onClick: () => {},
975
+ },
976
+ {
977
+ icon: <BulletedListIcon />,
978
+ hidden: (state) => !activePlugins?.includes('bulleted-list') || state.isTable,
979
+ onClick: (editor) =>
980
+ editor
981
+ .chain()
982
+ .focus()
983
+ .toggleBulletList()
984
+ .run(),
985
+ isActive: (state) => state.isBulletList,
986
+ },
987
+ {
988
+ icon: <NumberedListIcon />,
989
+ hidden: (state) => !activePlugins?.includes('numbered-list') || state.isTable,
990
+ onClick: (editor) =>
991
+ editor
992
+ .chain()
993
+ .focus()
994
+ .toggleOrderedList()
995
+ .run(),
996
+ isActive: (state) => state.isOrderedList,
997
+ },
998
+ {
999
+ icon: <Undo />,
1000
+ hidden: (state) => !activePlugins?.includes('undo') || state.isTable,
1001
+ onClick: (editor) =>
1002
+ editor
1003
+ .chain()
1004
+ .focus()
1005
+ .undo()
1006
+ .run(),
1007
+ isDisabled: (state) => !state.canUndo,
1008
+ },
1009
+ {
1010
+ icon: <Redo />,
1011
+ hidden: (state) => !activePlugins?.includes('redo') || state.isTable,
1012
+ onClick: (editor) =>
1013
+ editor
1014
+ .chain()
1015
+ .focus()
1016
+ .redo()
1017
+ .run(),
1018
+ isDisabled: (state) => !state.canRedo,
1019
+ },
1020
+ ],
1021
+ [activePlugins, editor, spanishConfig, specialConfig, setShowPicker],
1022
+ );
701
1023
 
702
1024
  return (
703
1025
  <div className={names} style={{ ...customStyles }} onMouseDown={handleMouseDown}>
704
- {!editorState.customToolbarActive && (
1026
+ {!editorState.hideDefaultToolbar && (
705
1027
  <div className={classes.defaultToolbar} tabIndex="1">
706
1028
  <div className={classes.buttonsContainer}>
1029
+ {toolbarButtons
1030
+ .filter((btn) => !btn.hidden?.(editorState))
1031
+ .map((btn, index) => {
1032
+ const disabled = btn.isDisabled?.(editorState);
1033
+ const active = btn.isActive?.(editorState);
1034
+
1035
+ return (
1036
+ <button
1037
+ key={index}
1038
+ disabled={disabled}
1039
+ onClick={(e) => {
1040
+ e.preventDefault();
1041
+ btn.onClick(editor);
1042
+ }}
1043
+ className={classNames(classes.button, { [classes.active]: active })}
1044
+ >
1045
+ {btn.icon}
1046
+ </button>
1047
+ );
1048
+ })}
1049
+ </div>
1050
+ {activePlugins?.includes('responseArea') && (
707
1051
  <button
708
- onClick={(e) => {
709
- e.preventDefault();
710
- editor
711
- .chain()
712
- .focus()
713
- .insertTable()
714
- .run();
715
- }}
716
- disabled={!editorState.canTable}
717
- className={classNames(classes.button, { [classes.active]: editorState.isTable })}
718
- >
719
- <GridOn />
720
- </button>
721
- <button
722
- onClick={(e) => {
723
- e.preventDefault();
1052
+ onClick={() => {
724
1053
  editor
725
1054
  .chain()
726
1055
  .focus()
727
- .toggleBold()
1056
+ .insertResponseArea(responseAreaProps.type)
728
1057
  .run();
729
1058
  }}
730
- disabled={!editorState.canBold}
731
- className={classNames(classes.button, { [classes.active]: editorState.isBold })}
732
- >
733
- <Bold />
734
- </button>
735
- <button
736
- onClick={() =>
737
- editor
738
- .chain()
739
- .focus()
740
- .toggleItalic()
741
- .run()
742
- }
743
- disabled={!editorState.canItalic}
744
- active={editorState.isItalic}
745
- className={classNames(classes.button, { [classes.active]: editorState.isItalic })}
746
- >
747
- <Italic />
748
- </button>
749
- <button
750
- onClick={() =>
751
- editor
752
- .chain()
753
- .focus()
754
- .toggleStrike()
755
- .run()
756
- }
757
- disabled={!editorState.canStrike}
758
- active={editorState.isStrike}
759
- className={classNames(classes.button, { [classes.active]: editorState.isStrike })}
760
- >
761
- <Strikethrough />
762
- </button>
763
- <button
764
- onClick={() =>
765
- editor
766
- .chain()
767
- .focus()
768
- .toggleCode()
769
- .run()
770
- }
771
- disabled={!editorState.canCode}
772
- active={editorState.isCode}
773
- className={classNames(classes.button, { [classes.active]: editorState.isCode })}
774
- >
775
- <Code />
776
- </button>
777
- {/*<button*/}
778
- {/* onClick={() =>*/}
779
- {/* editor*/}
780
- {/* .chain()*/}
781
- {/* .focus()*/}
782
- {/* .unsetAllMarks()*/}
783
- {/* .run()*/}
784
- {/* }*/}
785
- {/*>*/}
786
- {/* Clear marks*/}
787
- {/*</button>*/}
788
- {/*<button*/}
789
- {/* onClick={() =>*/}
790
- {/* editor*/}
791
- {/* .chain()*/}
792
- {/* .focus()*/}
793
- {/* .clearNodes()*/}
794
- {/* .run()*/}
795
- {/* }*/}
796
- {/*>*/}
797
- {/* Clear nodes*/}
798
- {/*</button>*/}
799
- {/*<button*/}
800
- {/* onClick={() =>*/}
801
- {/* editor*/}
802
- {/* .chain()*/}
803
- {/* .focus()*/}
804
- {/* .setParagraph()*/}
805
- {/* .run()*/}
806
- {/* }*/}
807
- {/* className={editorState.isParagraph ? classes.isActive : ''}*/}
808
- {/*>*/}
809
- {/* Paragraph*/}
810
- {/*</button>*/}
811
- {/*<button*/}
812
- {/* onClick={() =>*/}
813
- {/* editor*/}
814
- {/* .chain()*/}
815
- {/* .focus()*/}
816
- {/* .toggleHeading({ level: 1 })*/}
817
- {/* .run()*/}
818
- {/* }*/}
819
- {/* className={editorState.isHeading1 ? classes.isActive : ''}*/}
820
- {/*>*/}
821
- {/* H1*/}
822
- {/*</button>*/}
823
- {/*<button*/}
824
- {/* onClick={() =>*/}
825
- {/* editor*/}
826
- {/* .chain()*/}
827
- {/* .focus()*/}
828
- {/* .toggleHeading({ level: 2 })*/}
829
- {/* .run()*/}
830
- {/* }*/}
831
- {/* className={editorState.isHeading2 ? classes.isActive : ''}*/}
832
- {/*>*/}
833
- {/* H2*/}
834
- {/*</button>*/}
835
- <button
836
- onClick={() =>
837
- editor
838
- .chain()
839
- .focus()
840
- .toggleUnderline()
841
- .run()
842
- }
843
- className={classNames(classes.button, { [classes.active]: editorState.isUnderline })}
844
- >
845
- <Underline />
846
- </button>
847
- <button
848
- onClick={() =>
849
- editor
850
- .chain()
851
- .focus()
852
- .toggleSubscript()
853
- .run()
854
- }
855
- className={classNames(classes.button, { [classes.active]: editorState.isSubScript })}
856
- >
857
- <SubscriptIcon />
858
- </button>
859
- <button
860
- onClick={() =>
861
- editor
862
- .chain()
863
- .focus()
864
- .toggleSuperscript()
865
- .run()
866
- }
867
- className={classNames(classes.button, { [classes.active]: editorState.isSuperScript })}
868
- >
869
- <SuperscriptIcon />
870
- </button>
871
- <button
872
- onClick={() =>
873
- editor
874
- .chain()
875
- .focus()
876
- .setImageUploadNode()
877
- .run()
878
- }
879
- className={classNames(classes.button, { [classes.active]: editorState.isSuperScript })}
880
- >
881
- <ImageIcon />
882
- </button>
883
- <button
884
- onClick={() =>
885
- editor
886
- .chain()
887
- .focus()
888
- .insertMedia({
889
- tag: 'video',
890
- })
891
- .run()
892
- }
893
- className={classNames(classes.button)}
894
- >
895
- <TheatersIcon />
896
- </button>
897
- <button
898
- onClick={() =>
899
- editor
900
- .chain()
901
- .focus()
902
- .insertMedia({
903
- tag: 'audio',
904
- })
905
- .run()
906
- }
907
- className={classNames(classes.button)}
908
- >
909
- <VolumeUpIcon />
910
- </button>
911
- <button
912
- onClick={() =>
913
- editor.commands.openCSSClassDialog()
914
- }
915
- className={classNames(classes.button)}
916
- >
917
- <CSSIcon />
918
- </button>
919
- <button
920
- onClick={() =>
921
- editor
922
- .chain()
923
- .focus()
924
- .toggleHeading({ level: 3 })
925
- .run()
926
- }
927
- className={classNames(classes.button, { [classes.active]: editorState.isHeading3 })}
928
- >
929
- <HeadingIcon />
930
- </button>
931
- {/*<button*/}
932
- {/* onClick={() =>*/}
933
- {/* editor*/}
934
- {/* .chain()*/}
935
- {/* .focus()*/}
936
- {/* .toggleHeading({ level: 3 })*/}
937
- {/* .run()*/}
938
- {/* }*/}
939
- {/* className={classNames(classes.button, { [classes.active]: editorState.isHeading3 })}*/}
940
- {/*>*/}
941
- {/* <Image />*/}
942
- {/*</button>*/}
943
- {/*<button*/}
944
- {/* onClick={() =>*/}
945
- {/* editor*/}
946
- {/* .chain()*/}
947
- {/* .focus()*/}
948
- {/* .toggleHeading({ level: 4 })*/}
949
- {/* .run()*/}
950
- {/* }*/}
951
- {/* className={editorState.isHeading4 ? classes.isActive : ''}*/}
952
- {/*>*/}
953
- {/* H4*/}
954
- {/*</button>*/}
955
- {/*<button*/}
956
- {/* onClick={() =>*/}
957
- {/* editor*/}
958
- {/* .chain()*/}
959
- {/* .focus()*/}
960
- {/* .toggleHeading({ level: 5 })*/}
961
- {/* .run()*/}
962
- {/* }*/}
963
- {/* className={editorState.isHeading5 ? classes.isActive : ''}*/}
964
- {/*>*/}
965
- {/* H5*/}
966
- {/*</button>*/}
967
- {/*<button*/}
968
- {/* onClick={() =>*/}
969
- {/* editor*/}
970
- {/* .chain()*/}
971
- {/* .focus()*/}
972
- {/* .toggleHeading({ level: 6 })*/}
973
- {/* .run()*/}
974
- {/* }*/}
975
- {/* className={editorState.isHeading6 ? classes.isActive : ''}*/}
976
- {/*>*/}
977
- {/* H6*/}
978
- {/*</button>*/}
979
- <button
980
- onClick={() =>
981
- editor
982
- .chain()
983
- .focus()
984
- .insertMath('')
985
- .run()
986
- }
987
1059
  className={classes.button}
988
1060
  >
989
- <Functions />
990
- </button>
991
- <button onClick={() => setShowPicker(spanishConfig)} className={classes.button}>
992
- <CharacterIcon letter="ñ" />
1061
+ <ToolbarIcon />
993
1062
  </button>
994
- <button onClick={() => setShowPicker(specialConfig)} className={classes.button}>
995
- <CharacterIcon letter="€" />
996
- </button>
997
- <button onClick={() => {}} className={classes.button}>
998
- <TextAlignIcon editor={editor} />
999
- </button>
1000
- <button
1001
- onClick={() =>
1002
- editor
1003
- .chain()
1004
- .focus()
1005
- .toggleBulletList()
1006
- .run()
1007
- }
1008
- className={classNames(classes.button, { [classes.active]: editorState.isBulletList })}
1009
- >
1010
- <BulletedListIcon />
1011
- </button>
1012
- <button
1013
- onClick={() =>
1014
- editor
1015
- .chain()
1016
- .focus()
1017
- .toggleOrderedList()
1018
- .run()
1019
- }
1020
- className={classNames(classes.button, { [classes.active]: editorState.isOrderedList })}
1021
- >
1022
- <NumberedListIcon />
1023
- </button>
1024
- {/*<button*/}
1025
- {/* onClick={() =>*/}
1026
- {/* editor*/}
1027
- {/* .chain()*/}
1028
- {/* .focus()*/}
1029
- {/* .toggleCodeBlock()*/}
1030
- {/* .run()*/}
1031
- {/* }*/}
1032
- {/* className={classNames(classes.button, { [classes.active]: editorState.isCodeBlock })}*/}
1033
- {/*>*/}
1034
- {/* Code block*/}
1035
- {/*</button>*/}
1036
- {/*<button*/}
1037
- {/* onClick={() =>*/}
1038
- {/* editor*/}
1039
- {/* .chain()*/}
1040
- {/* .focus()*/}
1041
- {/* .toggleBlockquote()*/}
1042
- {/* .run()*/}
1043
- {/* }*/}
1044
- {/* className={classNames(classes.button, { [classes.active]: editorState.isBlockquote })}*/}
1045
- {/*>*/}
1046
- {/* Blockquote*/}
1047
- {/*</button>*/}
1048
- {/*<button*/}
1049
- {/* onClick={() =>*/}
1050
- {/* editor*/}
1051
- {/* .chain()*/}
1052
- {/* .focus()*/}
1053
- {/* .setHorizontalRule()*/}
1054
- {/* .run()*/}
1055
- {/* }*/}
1056
- {/*>*/}
1057
- {/* Horizontal rule*/}
1058
- {/*</button>*/}
1059
- {/*<button*/}
1060
- {/* onClick={() =>*/}
1061
- {/* editor*/}
1062
- {/* .chain()*/}
1063
- {/* .focus()*/}
1064
- {/* .setHardBreak()*/}
1065
- {/* .run()*/}
1066
- {/* }*/}
1067
- {/*>*/}
1068
- {/* Hard break*/}
1069
- {/*</button>*/}
1070
- <button
1071
- onClick={() =>
1072
- editor
1073
- .chain()
1074
- .focus()
1075
- .undo()
1076
- .run()
1077
- }
1078
- disabled={!editorState.canUndo}
1079
- className={classes.button}
1080
- >
1081
- <Undo />
1082
- </button>
1083
- <button
1084
- onClick={() =>
1085
- editor
1086
- .chain()
1087
- .focus()
1088
- .redo()
1089
- .run()
1090
- }
1091
- disabled={!editorState.canRedo}
1092
- className={classes.button}
1093
- >
1094
- <Redo />
1095
- </button>
1096
- </div>
1097
- <button
1098
- onClick={() => {
1099
- editor
1100
- .chain()
1101
- .focus()
1102
- .insertResponseArea(responseAreaProps.type)
1103
- .run();
1104
- }}
1105
- className={classes.button}
1106
- >
1107
- <ToolbarIcon />
1108
- </button>
1063
+ )}
1109
1064
 
1110
1065
  <DoneButton
1111
1066
  onClick={() => {
@@ -1238,6 +1193,26 @@ export const EditableHtml = (props) => {
1238
1193
  ...defaultToolbarOpts,
1239
1194
  ...toolbarOpts,
1240
1195
  };
1196
+ const activePluginsToUse = useMemo(() => {
1197
+ let { customPlugins } = props.pluginProps || {};
1198
+
1199
+ customPlugins = customPlugins || [];
1200
+
1201
+ return buildPlugins(props.activePlugins, customPlugins, {
1202
+ math: {},
1203
+ textAlign: {},
1204
+ html: {},
1205
+ extraCSSRules: props.extraCSSRules || {},
1206
+ image: {},
1207
+ toolbar: {},
1208
+ table: {},
1209
+ responseArea: {},
1210
+ languageCharacters: props.languageCharactersProps,
1211
+ keyPadCharacterRef: {},
1212
+ setKeypadInteraction: {},
1213
+ media: {},
1214
+ });
1215
+ }, [props]);
1241
1216
  const extensions = [
1242
1217
  TextStyleKit,
1243
1218
  StarterKit,
@@ -1263,6 +1238,7 @@ export const EditableHtml = (props) => {
1263
1238
  toolbarOpts: toolbarOptsToUse,
1264
1239
  imageHandling: {
1265
1240
  disableImageAlignmentButtons: props.disableImageAlignmentButtons,
1241
+ onDone: () => props.onDone?.(editor.getHTML()),
1266
1242
  onDelete:
1267
1243
  props.imageSupport &&
1268
1244
  props.imageSupport.delete &&
@@ -1326,7 +1302,7 @@ export const EditableHtml = (props) => {
1326
1302
  uploadSoundSupport: props.uploadSoundSupport,
1327
1303
  }),
1328
1304
  CSSMark.configure({
1329
- extraCSSRules: props.extraCSSRules
1305
+ extraCSSRules: props.extraCSSRules,
1330
1306
  }),
1331
1307
  ];
1332
1308
  const editor = useEditor({
@@ -1433,7 +1409,11 @@ export const EditableHtml = (props) => {
1433
1409
  }, [props]);
1434
1410
 
1435
1411
  return (
1436
- <EditorContainer {...{ ...props, toolbarOpts: toolbarOptsToUse }} editorState={editorState} editor={editor}>
1412
+ <EditorContainer
1413
+ {...{ ...props, activePlugins: activePluginsToUse, toolbarOpts: toolbarOptsToUse }}
1414
+ editorState={editorState}
1415
+ editor={editor}
1416
+ >
1437
1417
  {editor && (
1438
1418
  <EditorContent
1439
1419
  style={{