@ioca/react 1.5.3 → 1.5.5

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.
Files changed (57) hide show
  1. package/lib/cjs/components/editor/controls.js +31 -40
  2. package/lib/cjs/components/editor/controls.js.map +1 -1
  3. package/lib/cjs/components/editor/editor.js +204 -41
  4. package/lib/cjs/components/editor/editor.js.map +1 -1
  5. package/lib/cjs/components/editor/memtion.js +171 -0
  6. package/lib/cjs/components/editor/memtion.js.map +1 -0
  7. package/lib/cjs/components/image/image.js +46 -30
  8. package/lib/cjs/components/image/image.js.map +1 -1
  9. package/lib/cjs/components/input/textarea.js +12 -5
  10. package/lib/cjs/components/input/textarea.js.map +1 -1
  11. package/lib/cjs/components/modal/hookModal.js +1 -1
  12. package/lib/cjs/components/modal/hookModal.js.map +1 -1
  13. package/lib/cjs/components/picker/colors/footer.js +1 -1
  14. package/lib/cjs/components/picker/colors/footer.js.map +1 -1
  15. package/lib/cjs/components/popconfirm/popconfirm.js +3 -3
  16. package/lib/cjs/components/popconfirm/popconfirm.js.map +1 -1
  17. package/lib/cjs/components/tabs/tabs.js +95 -37
  18. package/lib/cjs/components/tabs/tabs.js.map +1 -1
  19. package/lib/cjs/js/hooks.js +60 -40
  20. package/lib/cjs/js/hooks.js.map +1 -1
  21. package/lib/css/colors.css +13 -8
  22. package/lib/css/index.css +1 -1
  23. package/lib/css/index.css.map +1 -1
  24. package/lib/css/input.css +12 -6
  25. package/lib/css/reset.css +2 -5
  26. package/lib/css/utilities.css +9 -10
  27. package/lib/es/components/editor/controls.js +32 -37
  28. package/lib/es/components/editor/controls.js.map +1 -1
  29. package/lib/es/components/editor/editor.js +205 -42
  30. package/lib/es/components/editor/editor.js.map +1 -1
  31. package/lib/es/components/editor/memtion.js +160 -0
  32. package/lib/es/components/editor/memtion.js.map +1 -0
  33. package/lib/es/components/image/image.js +47 -31
  34. package/lib/es/components/image/image.js.map +1 -1
  35. package/lib/es/components/image/index.js +2 -2
  36. package/lib/es/components/image/list.js +2 -2
  37. package/lib/es/components/image/list.js.map +1 -1
  38. package/lib/es/components/input/textarea.js +12 -5
  39. package/lib/es/components/input/textarea.js.map +1 -1
  40. package/lib/es/components/modal/hookModal.js +1 -1
  41. package/lib/es/components/modal/hookModal.js.map +1 -1
  42. package/lib/es/components/picker/colors/footer.js +1 -1
  43. package/lib/es/components/picker/colors/footer.js.map +1 -1
  44. package/lib/es/components/popconfirm/popconfirm.js +3 -3
  45. package/lib/es/components/popconfirm/popconfirm.js.map +1 -1
  46. package/lib/es/components/tabs/tabs.js +95 -37
  47. package/lib/es/components/tabs/tabs.js.map +1 -1
  48. package/lib/es/components/upload/renderFile.js +2 -2
  49. package/lib/es/components/upload/renderFile.js.map +1 -1
  50. package/lib/es/js/hooks.js +61 -41
  51. package/lib/es/js/hooks.js.map +1 -1
  52. package/lib/index.js +608 -195
  53. package/lib/types/components/editor/type.d.ts +25 -12
  54. package/lib/types/components/image/image.d.ts +2 -2
  55. package/lib/types/components/image/index.d.ts +2 -2
  56. package/lib/types/components/input/type.d.ts +1 -0
  57. package/package.json +1 -1
@@ -4,89 +4,80 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var material = require('@ricons/material');
7
- var xss = require('xss');
8
7
  var button = require('../button/button.js');
9
8
  var icon = require('../icon/icon.js');
10
9
 
11
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
12
-
13
- var xss__default = /*#__PURE__*/_interopDefaultCompat(xss);
14
-
15
- const { escapeAttrValue } = xss__default;
16
10
  const exec = (a, b, c) => {
17
11
  if (typeof document === "undefined")
18
12
  return;
19
13
  return document.execCommand(a, b, c);
20
14
  };
15
+ const escapeHtmlAttr = (value) => value
16
+ .replaceAll("&", "&")
17
+ .replaceAll('"', """)
18
+ .replaceAll("<", "&lt;")
19
+ .replaceAll(">", "&gt;");
21
20
  const xssOptions = {
22
- onIgnoreTagAttr: function (tag, name, value) {
23
- if (["data-", "style"].includes(name.substr(0, 5))) {
24
- return name + '="' + escapeAttrValue(value) + '"';
21
+ onIgnoreTagAttr(tag, name, value) {
22
+ if (["class", "contenteditable"].includes(name)) {
23
+ return name + '="' + escapeHtmlAttr(value) + '"';
24
+ }
25
+ if (["data-", "style"].includes(name.substring(0, 5))) {
26
+ return name + '="' + escapeHtmlAttr(value) + '"';
25
27
  }
26
28
  },
27
29
  };
30
+ const handleMouseDown = (e) => {
31
+ e.preventDefault();
32
+ };
28
33
  const fnMap = {
29
34
  bold: {
30
35
  icon: jsxRuntime.jsx(material.FormatBoldRound, {}),
31
36
  onClick: () => exec("bold"),
32
- tip: "粗体",
33
37
  },
34
38
  italic: {
35
39
  icon: jsxRuntime.jsx(material.FormatItalicRound, {}),
36
40
  onClick: () => exec("italic"),
37
- tip: "斜体",
38
41
  },
39
42
  underline: {
40
43
  icon: jsxRuntime.jsx(material.FormatUnderlinedRound, {}),
41
44
  onClick: () => exec("underline"),
42
- tip: "下划线",
43
45
  },
44
46
  strike: {
45
47
  icon: jsxRuntime.jsx(material.StrikethroughSRound, {}),
46
48
  onClick: () => exec("strikeThrough"),
47
- tip: "删除线",
48
49
  },
49
50
  redo: {
50
51
  icon: jsxRuntime.jsx(material.RedoRound, {}),
51
52
  onClick: () => exec("redo"),
52
- tip: "重做",
53
53
  },
54
54
  undo: {
55
55
  icon: jsxRuntime.jsx(material.UndoRound, {}),
56
56
  onClick: () => exec("undo"),
57
- tip: "撤销",
58
57
  },
59
- // color: {
60
- // icon: <FormatColorTextRound />,
61
- // onClick: () => exec("foreColor", false, ""),
62
- // },
63
- // backColor: {
64
- // icon: <FormatColorFillRound />,
65
- // onClick: () => exec("backColor", false, ""),
66
- // },
67
58
  clear: {
68
59
  icon: jsxRuntime.jsx(material.ClearAllRound, {}),
69
60
  onClick: () => exec("removeFormat"),
70
- tip: "清除格式",
71
61
  },
72
62
  };
73
- const aliasMap = {
74
- simple: ["undo", "redo", "bold", "italic", "underline", "strike", "clear"],
75
- all: Object.keys(fnMap),
76
- };
77
- function getControls(fns, options) {
78
- const { controlBtnProps } = options;
79
- const keys = typeof fns === "string" ? aliasMap[fns] : fns;
80
- return keys.map((k) => {
81
- if (fnMap[k]) {
82
- const { icon: icon$1, render, tip, onClick } = fnMap[k];
83
- if (render) {
84
- return render(options);
85
- }
86
- return (jsxRuntime.jsxs(button.default, { ...controlBtnProps, onClick: onClick, children: [jsxRuntime.jsx(icon.default, { icon: icon$1 }), tip && jsxRuntime.jsx("span", { className: 'i-editor-control-tip', children: tip })] }, k));
87
- }
88
- return jsxRuntime.jsx(jsxRuntime.Fragment, {}, k);
63
+ const defaultKeys = [
64
+ "undo",
65
+ "redo",
66
+ "bold",
67
+ "italic",
68
+ "underline",
69
+ "strike",
70
+ "clear",
71
+ ];
72
+ const typedFnMap = fnMap;
73
+ function getControls(options) {
74
+ const { controlBtnProps, addtionControls, getSelection } = options;
75
+ const controls = defaultKeys.map((k) => {
76
+ const { icon: icon$1, onClick } = typedFnMap[k];
77
+ return (jsxRuntime.jsx(button.default, { ...controlBtnProps, onMouseDown: handleMouseDown, onClick: onClick, children: jsxRuntime.jsx(icon.default, { icon: icon$1 }) }, k));
89
78
  });
79
+ const extControls = (addtionControls ?? []).map((item, index) => (jsxRuntime.jsx(button.default, { ...controlBtnProps, onMouseDown: handleMouseDown, onClick: (e) => item.onClick?.(getSelection(), e), children: item.icon }, `addtion-${index}`)));
80
+ return [...controls, ...extControls];
90
81
  }
91
82
 
92
83
  exports.default = getControls;
@@ -1 +1 @@
1
- {"version":3,"file":"controls.js","sources":["../../../../packages/components/editor/controls.tsx"],"sourcesContent":["import {\r\n\tClearAllRound,\r\n\tFormatBoldRound,\r\n\tFormatItalicRound,\r\n\tFormatUnderlinedRound,\r\n\tRedoRound,\r\n\tStrikethroughSRound,\r\n\tUndoRound,\r\n} from \"@ricons/material\";\r\nimport { Fragment } from \"react/jsx-runtime\";\r\nimport xss from \"xss\";\r\nimport Button from \"../button\";\r\nimport Icon from \"../icon\";\r\n\r\nconst { escapeAttrValue } = xss as unknown as {\r\n\tescapeAttrValue: (value: string) => string;\r\n};\r\n\r\nexport const exec = (a, b?, c?) => {\r\n\tif (typeof document === \"undefined\") return;\r\n\treturn document.execCommand(a, b, c);\r\n};\r\n\r\nexport const xssOptions = {\r\n\tonIgnoreTagAttr: function (tag, name, value) {\r\n\t\tif ([\"data-\", \"style\"].includes(name.substr(0, 5))) {\r\n\t\t\treturn name + '=\"' + escapeAttrValue(value) + '\"';\r\n\t\t}\r\n\t},\r\n};\r\n\r\nconst fnMap = {\r\n\tbold: {\r\n\t\ticon: <FormatBoldRound />,\r\n\t\tonClick: () => exec(\"bold\"),\r\n\t\ttip: \"粗体\",\r\n\t},\r\n\titalic: {\r\n\t\ticon: <FormatItalicRound />,\r\n\t\tonClick: () => exec(\"italic\"),\r\n\t\ttip: \"斜体\",\r\n\t},\r\n\tunderline: {\r\n\t\ticon: <FormatUnderlinedRound />,\r\n\t\tonClick: () => exec(\"underline\"),\r\n\t\ttip: \"下划线\",\r\n\t},\r\n\tstrike: {\r\n\t\ticon: <StrikethroughSRound />,\r\n\t\tonClick: () => exec(\"strikeThrough\"),\r\n\t\ttip: \"删除线\",\r\n\t},\r\n\tredo: {\r\n\t\ticon: <RedoRound />,\r\n\t\tonClick: () => exec(\"redo\"),\r\n\t\ttip: \"重做\",\r\n\t},\r\n\tundo: {\r\n\t\ticon: <UndoRound />,\r\n\t\tonClick: () => exec(\"undo\"),\r\n\t\ttip: \"撤销\",\r\n\t},\r\n\t// color: {\r\n\t// \ticon: <FormatColorTextRound />,\r\n\t// \tonClick: () => exec(\"foreColor\", false, \"\"),\r\n\t// },\r\n\t// backColor: {\r\n\t// \ticon: <FormatColorFillRound />,\r\n\t// \tonClick: () => exec(\"backColor\", false, \"\"),\r\n\t// },\r\n\tclear: {\r\n\t\ticon: <ClearAllRound />,\r\n\t\tonClick: () => exec(\"removeFormat\"),\r\n\t\ttip: \"清除格式\",\r\n\t},\r\n};\r\n\r\nconst aliasMap = {\r\n\tsimple: [\"undo\", \"redo\", \"bold\", \"italic\", \"underline\", \"strike\", \"clear\"],\r\n\tall: Object.keys(fnMap),\r\n};\r\n\r\nexport default function getControls(fns, options) {\r\n\tconst { controlBtnProps } = options;\r\n\tconst keys = typeof fns === \"string\" ? aliasMap[fns] : fns;\r\n\r\n\treturn keys.map((k) => {\r\n\t\tif (fnMap[k]) {\r\n\t\t\tconst { icon, render, tip, onClick } = fnMap[k];\r\n\r\n\t\t\tif (render) {\r\n\t\t\t\treturn render(options);\r\n\t\t\t}\r\n\r\n\t\t\treturn (\r\n\t\t\t\t<Button key={k} {...controlBtnProps} onClick={onClick}>\r\n\t\t\t\t\t<Icon icon={icon} />\r\n\t\t\t\t\t{tip && <span className='i-editor-control-tip'>{tip}</span>}\r\n\t\t\t\t</Button>\r\n\t\t\t);\r\n\t\t}\r\n\t\treturn <Fragment key={k} />;\r\n\t});\r\n}\r\n"],"names":["xss","_jsx","FormatBoldRound","FormatItalicRound","FormatUnderlinedRound","StrikethroughSRound","RedoRound","UndoRound","ClearAllRound","icon","_jsxs","Button","Icon","Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"controls.js","sources":["../../../../packages/components/editor/controls.tsx"],"sourcesContent":["import {\r\n ClearAllRound,\r\n FormatBoldRound,\r\n FormatItalicRound,\r\n FormatUnderlinedRound,\r\n RedoRound,\r\n StrikethroughSRound,\r\n UndoRound,\r\n} from \"@ricons/material\";\r\nimport { MouseEvent, ReactNode } from \"react\";\r\nimport { type IFilterXSSOptions } from \"xss\";\r\nimport Button from \"../button\";\r\nimport { IButton } from \"../button/type\";\r\nimport Icon from \"../icon\";\r\nimport { IEditorAddtionControl } from \"./type\";\r\n\r\nexport const exec = (a, b?, c?) => {\r\n if (typeof document === \"undefined\") return;\r\n return document.execCommand(a, b, c);\r\n};\r\n\r\nconst escapeHtmlAttr = (value: string) =>\r\n value\r\n .replaceAll(\"&\", \"&amp;\")\r\n .replaceAll('\"', \"&quot;\")\r\n .replaceAll(\"<\", \"&lt;\")\r\n .replaceAll(\">\", \"&gt;\");\r\n\r\nexport const xssOptions: IFilterXSSOptions = {\r\n onIgnoreTagAttr(tag, name, value) {\r\n if ([\"class\", \"contenteditable\"].includes(name)) {\r\n return name + '=\"' + escapeHtmlAttr(value) + '\"';\r\n }\r\n if ([\"data-\", \"style\"].includes(name.substring(0, 5))) {\r\n return name + '=\"' + escapeHtmlAttr(value) + '\"';\r\n }\r\n },\r\n};\r\n\r\nconst handleMouseDown = (e: MouseEvent<HTMLElement>) => {\r\n e.preventDefault();\r\n};\r\n\r\nconst fnMap = {\r\n bold: {\r\n icon: <FormatBoldRound />,\r\n onClick: () => exec(\"bold\"),\r\n },\r\n italic: {\r\n icon: <FormatItalicRound />,\r\n onClick: () => exec(\"italic\"),\r\n },\r\n underline: {\r\n icon: <FormatUnderlinedRound />,\r\n onClick: () => exec(\"underline\"),\r\n },\r\n strike: {\r\n icon: <StrikethroughSRound />,\r\n onClick: () => exec(\"strikeThrough\"),\r\n },\r\n redo: {\r\n icon: <RedoRound />,\r\n onClick: () => exec(\"redo\"),\r\n },\r\n undo: {\r\n icon: <UndoRound />,\r\n onClick: () => exec(\"undo\"),\r\n },\r\n clear: {\r\n icon: <ClearAllRound />,\r\n onClick: () => exec(\"removeFormat\"),\r\n },\r\n};\r\n\r\nconst defaultKeys = [\r\n \"undo\",\r\n \"redo\",\r\n \"bold\",\r\n \"italic\",\r\n \"underline\",\r\n \"strike\",\r\n \"clear\",\r\n] as const;\r\n\r\ntype ControlKey = (typeof defaultKeys)[number];\r\ntype ControlItem = {\r\n icon: ReactNode;\r\n onClick: () => void;\r\n};\r\n\r\nconst typedFnMap: Record<ControlKey, ControlItem> = fnMap;\r\n\r\nexport default function getControls(options: {\r\n controlBtnProps: IButton;\r\n addtionControls?: IEditorAddtionControl[];\r\n getSelection: () => Range | null;\r\n}) {\r\n const { controlBtnProps, addtionControls, getSelection } = options;\r\n\r\n const controls = defaultKeys.map((k) => {\r\n const { icon, onClick } = typedFnMap[k];\r\n\r\n return (\r\n <Button\r\n key={k}\r\n {...controlBtnProps}\r\n onMouseDown={handleMouseDown}\r\n onClick={onClick}\r\n >\r\n <Icon icon={icon} />\r\n </Button>\r\n );\r\n });\r\n\r\n const extControls = (addtionControls ?? []).map((item, index) => (\r\n <Button\r\n key={`addtion-${index}`}\r\n {...controlBtnProps}\r\n onMouseDown={handleMouseDown}\r\n onClick={(e) => item.onClick?.(getSelection(), e)}\r\n >\r\n {item.icon}\r\n </Button>\r\n ));\r\n\r\n return [...controls, ...extControls];\r\n}\r\n"],"names":["_jsx","FormatBoldRound","FormatItalicRound","FormatUnderlinedRound","StrikethroughSRound","RedoRound","UndoRound","ClearAllRound","icon","Button","Icon"],"mappings":";;;;;;;;;AAgBO,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAE,EAAE,CAAE,KAAI;IAC9B,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE;IACrC,OAAO,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AACxC;AAEA,MAAM,cAAc,GAAG,CAAC,KAAa,KACjC;AACK,KAAA,UAAU,CAAC,GAAG,EAAE,OAAO;AACvB,KAAA,UAAU,CAAC,GAAG,EAAE,QAAQ;AACxB,KAAA,UAAU,CAAC,GAAG,EAAE,MAAM;AACtB,KAAA,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;AAEzB,MAAM,UAAU,GAAsB;AACzC,IAAA,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAA;QAC5B,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC7C,OAAO,IAAI,GAAG,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,GAAG;QACpD;AACA,QAAA,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;YACnD,OAAO,IAAI,GAAG,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,GAAG;QACpD;IACJ,CAAC;;AAGL,MAAM,eAAe,GAAG,CAAC,CAA0B,KAAI;IACnD,CAAC,CAAC,cAAc,EAAE;AACtB,CAAC;AAED,MAAM,KAAK,GAAG;AACV,IAAA,IAAI,EAAE;QACF,IAAI,EAAEA,cAAA,CAACC,wBAAe,EAAA,EAAA,CAAG;AACzB,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC;AAC9B,KAAA;AACD,IAAA,MAAM,EAAE;QACJ,IAAI,EAAED,cAAA,CAACE,0BAAiB,EAAA,EAAA,CAAG;AAC3B,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC;AAChC,KAAA;AACD,IAAA,SAAS,EAAE;QACP,IAAI,EAAEF,cAAA,CAACG,8BAAqB,EAAA,EAAA,CAAG;AAC/B,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC;AACnC,KAAA;AACD,IAAA,MAAM,EAAE;QACJ,IAAI,EAAEH,cAAA,CAACI,4BAAmB,EAAA,EAAA,CAAG;AAC7B,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,eAAe,CAAC;AACvC,KAAA;AACD,IAAA,IAAI,EAAE;QACF,IAAI,EAAEJ,cAAA,CAACK,kBAAS,EAAA,EAAA,CAAG;AACnB,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC;AAC9B,KAAA;AACD,IAAA,IAAI,EAAE;QACF,IAAI,EAAEL,cAAA,CAACM,kBAAS,EAAA,EAAA,CAAG;AACnB,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC;AAC9B,KAAA;AACD,IAAA,KAAK,EAAE;QACH,IAAI,EAAEN,cAAA,CAACO,sBAAa,EAAA,EAAA,CAAG;AACvB,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,cAAc,CAAC;AACtC,KAAA;CACJ;AAED,MAAM,WAAW,GAAG;IAChB,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,OAAO;CACD;AAQV,MAAM,UAAU,GAAoC,KAAK;AAE3C,SAAU,WAAW,CAAC,OAInC,EAAA;IACG,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,GAAG,OAAO;IAElE,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAI;QACnC,MAAM,QAAEC,MAAI,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;QAEvC,QACIR,cAAA,CAACS,cAAM,EAAA,EAAA,GAEC,eAAe,EACnB,WAAW,EAAE,eAAe,EAC5B,OAAO,EAAE,OAAO,EAAA,QAAA,EAEhBT,cAAA,CAACU,YAAI,EAAA,EAAC,IAAI,EAAEF,MAAI,EAAA,CAAI,EAAA,EALf,CAAC,CAMD;AAEjB,IAAA,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,eAAe,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,MACxDR,cAAA,CAACS,cAAM,EAAA,EAAA,GAEC,eAAe,EACnB,WAAW,EAAE,eAAe,EAC5B,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,GAAG,YAAY,EAAE,EAAE,CAAC,CAAC,EAAA,QAAA,EAEhD,IAAI,CAAC,IAAI,EAAA,EALL,CAAA,QAAA,EAAW,KAAK,CAAA,CAAE,CAMlB,CACZ,CAAC;AAEF,IAAA,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,WAAW,CAAC;AACxC;;;;;;"}
@@ -7,82 +7,245 @@ var classNames = require('classnames');
7
7
  var react = require('react');
8
8
  var xss = require('xss');
9
9
  var controls = require('./controls.js');
10
+ var memtion = require('./memtion.js');
10
11
 
11
12
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
12
13
 
13
14
  var classNames__default = /*#__PURE__*/_interopDefaultCompat(classNames);
14
15
  var xss__default = /*#__PURE__*/_interopDefaultCompat(xss);
15
16
 
17
+ const controlBtnProps = {
18
+ square: true,
19
+ flat: true,
20
+ size: "small",
21
+ };
16
22
  const Editor = (props) => {
17
- const { ref, width, height = "10em", placeholder, autosize, border = true, richPaste, controls: controls$1 = "simple", className, style, onInput, onPaste, onKeyDown, ...restProps } = props;
23
+ const { ref, value = "", width, height = "10em", placeholder, autosize, border = true, mode = "rich", hideControl, addtionControls, memtion: memtion$1, className, style, onChange, onEnter, onFocus, onBlur, onPaste, onMouseUp, onKeyUp, onKeyDown, ...restProps } = props;
18
24
  const editorRef = react.useRef(null);
19
- const controlBtnProps = {
20
- square: true,
21
- flat: true,
22
- size: "small",
25
+ const selectionRef = react.useRef(null);
26
+ const memtionTriggerRangeRef = react.useRef(null);
27
+ const pendingMemtionRef = react.useRef(false);
28
+ const [memtionVisible, setMemtionVisible] = react.useState(false);
29
+ const [memtionRect, setMemtionRect] = react.useState(null);
30
+ const [memtionKeyword, setMemtionKeyword] = react.useState("");
31
+ const [memtionActiveIndex, setMemtionActiveIndex] = react.useState(0);
32
+ const memtionOptions = react.useMemo(() => memtion.filterMemtionOptions(memtion$1?.options ?? [], memtionKeyword), [memtion$1?.options, memtionKeyword]);
33
+ const sanitizeValue = (nextValue) => {
34
+ if (mode === "plaintext") {
35
+ return nextValue === "\n" ? "" : nextValue;
36
+ }
37
+ const safeHtml = xss__default(nextValue, controls.xssOptions);
38
+ return safeHtml === "<br>" ? "" : safeHtml;
39
+ };
40
+ const rememberSelection = () => {
41
+ if (!editorRef.current)
42
+ return;
43
+ const selection = window.getSelection();
44
+ if (!selection?.rangeCount)
45
+ return;
46
+ const range = selection.getRangeAt(0);
47
+ const container = range.commonAncestorContainer;
48
+ const parent = container.nodeType === Node.ELEMENT_NODE
49
+ ? container
50
+ : container.parentElement;
51
+ if (!parent || !editorRef.current.contains(parent))
52
+ return;
53
+ selectionRef.current = range.cloneRange();
54
+ };
55
+ const setEditorValue = (nextValue) => {
56
+ if (!editorRef.current)
57
+ return;
58
+ const safeValue = sanitizeValue(nextValue);
59
+ if (mode === "plaintext") {
60
+ editorRef.current.textContent = safeValue;
61
+ return;
62
+ }
63
+ editorRef.current.innerHTML = safeValue;
64
+ };
65
+ const getEditorValue = (sanitize = false) => {
66
+ if (!editorRef.current)
67
+ return "";
68
+ const nextValue = mode === "plaintext"
69
+ ? (editorRef.current.textContent ?? "")
70
+ : editorRef.current.innerHTML;
71
+ return sanitize ? sanitizeValue(nextValue) : nextValue;
23
72
  };
24
- const handlePaste = async (e) => {
73
+ const hideMemtion = () => {
74
+ pendingMemtionRef.current = false;
75
+ memtionTriggerRangeRef.current = null;
76
+ setMemtionVisible(false);
77
+ setMemtionRect(null);
78
+ setMemtionKeyword("");
79
+ setMemtionActiveIndex(0);
80
+ };
81
+ const insertMemtion = (option) => {
82
+ const replaceRange = memtion.getMemtionReplaceRange(memtionTriggerRangeRef.current, selectionRef.current);
83
+ const range = memtion.insertMemtionOption({
84
+ editor: editorRef.current,
85
+ range: replaceRange,
86
+ mode,
87
+ memtion: memtion$1,
88
+ option,
89
+ sanitizeValue,
90
+ });
91
+ if (!range || !editorRef.current)
92
+ return;
93
+ selectionRef.current = range.cloneRange();
94
+ hideMemtion();
95
+ editorRef.current.dispatchEvent(new Event("input", { bubbles: true }));
96
+ };
97
+ const handlePaste = (e) => {
25
98
  onPaste?.(e);
26
- if (richPaste)
99
+ if (e.defaultPrevented)
27
100
  return;
28
101
  e.preventDefault();
102
+ if (mode === "plaintext") {
103
+ const text = e.clipboardData.getData("text/plain");
104
+ controls.exec("insertText", false, text);
105
+ return;
106
+ }
107
+ const html = e.clipboardData.getData("text/html");
108
+ if (html) {
109
+ controls.exec("insertHTML", false, sanitizeValue(html));
110
+ return;
111
+ }
29
112
  const text = e.clipboardData.getData("text/plain");
30
113
  controls.exec("insertText", false, text);
31
114
  };
32
115
  const handleKeyDown = (e) => {
33
116
  onKeyDown?.(e);
117
+ if (mode === "rich" &&
118
+ (e.key === "Backspace" || e.key === "Delete") &&
119
+ memtion.removeAdjacentMemtionTag(editorRef.current, e.key)) {
120
+ e.preventDefault();
121
+ rememberSelection();
122
+ editorRef.current?.dispatchEvent(new Event("input", { bubbles: true }));
123
+ return;
124
+ }
125
+ const memtionKey = memtion$1?.key ?? "@";
126
+ if (memtionVisible && e.key === " ") {
127
+ hideMemtion();
128
+ }
129
+ if (memtionVisible && memtionOptions.length) {
130
+ switch (e.key) {
131
+ case "ArrowDown":
132
+ e.preventDefault();
133
+ setMemtionActiveIndex((index) => index + 1 >= memtionOptions.length ? 0 : index + 1);
134
+ return;
135
+ case "ArrowUp":
136
+ e.preventDefault();
137
+ setMemtionActiveIndex((index) => index - 1 < 0 ? memtionOptions.length - 1 : index - 1);
138
+ return;
139
+ case "Enter":
140
+ e.preventDefault();
141
+ insertMemtion(memtionOptions[memtionActiveIndex]);
142
+ return;
143
+ }
144
+ }
145
+ if (memtion$1 && e.key === memtionKey) {
146
+ rememberSelection();
147
+ memtionTriggerRangeRef.current =
148
+ selectionRef.current?.cloneRange() ?? null;
149
+ pendingMemtionRef.current = true;
150
+ }
34
151
  switch (e.key) {
35
152
  case "Tab":
36
153
  e.preventDefault();
37
- controls.exec("insertHTML", false, "&#09;");
154
+ controls.exec(mode === "plaintext" ? "insertText" : "insertHTML", false, mode === "plaintext" ? "\t" : "&#09;");
38
155
  break;
39
156
  case "Enter":
157
+ if (!onEnter)
158
+ break;
40
159
  e.preventDefault();
41
- controls.exec("insertLineBreak");
42
- if (!editorRef.current)
43
- return;
44
- editorRef.current.scrollBy({
45
- top: 20,
46
- left: -1e3,
47
- });
48
- if (!autosize)
49
- return;
50
- editorRef.current.style.height = `${editorRef.current.scrollHeight}px`;
160
+ onEnter(e);
51
161
  break;
52
162
  }
53
163
  };
54
- react.useImperativeHandle(ref, () => {
55
- return {
56
- input: editorRef.current,
57
- setValue(html) {
58
- if (!editorRef.current)
59
- return;
60
- const safeHtml = xss__default(html, controls.xssOptions);
61
- editorRef.current.innerHTML = safeHtml;
62
- },
63
- getSafeValue() {
64
- const html = editorRef.current?.innerHTML ?? "";
65
- return xss__default(html, controls.xssOptions);
66
- },
67
- };
68
- });
164
+ react.useEffect(() => {
165
+ if (!editorRef.current)
166
+ return;
167
+ const nextValue = sanitizeValue(value);
168
+ if (getEditorValue(true) === nextValue)
169
+ return;
170
+ setEditorValue(nextValue);
171
+ if (autosize) {
172
+ editorRef.current.style.height = `${editorRef.current.scrollHeight}px`;
173
+ }
174
+ }, [autosize, mode, value]);
175
+ react.useEffect(() => {
176
+ if (!memtionOptions.length) {
177
+ setMemtionActiveIndex(0);
178
+ return;
179
+ }
180
+ setMemtionActiveIndex((index) => index >= memtionOptions.length ? 0 : index);
181
+ }, [memtionOptions]);
69
182
  const handleInput = (e) => {
70
- let html = editorRef.current?.innerHTML ?? "";
71
- if (["<br>", "\n"].includes(html) && editorRef.current) {
72
- html = "";
73
- editorRef.current.innerHTML = html;
183
+ const rawValue = getEditorValue();
184
+ let nextValue = sanitizeValue(rawValue);
185
+ if (!nextValue && rawValue && editorRef.current) {
186
+ nextValue = "";
187
+ setEditorValue(nextValue);
188
+ }
189
+ rememberSelection();
190
+ if (memtion$1 && (pendingMemtionRef.current || memtionVisible)) {
191
+ const memtionKey = memtion$1?.key ?? "@";
192
+ const memtionText = memtion.getMemtionText(memtionTriggerRangeRef.current, selectionRef.current);
193
+ if (!memtionText.startsWith(memtionKey) || /\s/.test(memtionText)) {
194
+ hideMemtion();
195
+ }
196
+ else {
197
+ const keyword = memtionText.slice(memtionKey.length);
198
+ pendingMemtionRef.current = false;
199
+ setMemtionRect(memtion.getSelectionRect(selectionRef.current));
200
+ setMemtionKeyword(keyword);
201
+ setMemtionActiveIndex(0);
202
+ setMemtionVisible(true);
203
+ }
204
+ }
205
+ if (autosize && editorRef.current) {
206
+ editorRef.current.style.height = `${editorRef.current.scrollHeight}px`;
207
+ }
208
+ onChange?.(nextValue, e);
209
+ };
210
+ const handleFocus = (e) => {
211
+ rememberSelection();
212
+ onFocus?.(e);
213
+ };
214
+ const handleBlur = (e) => {
215
+ hideMemtion();
216
+ onBlur?.(e);
217
+ };
218
+ const handleMouseUp = (e) => {
219
+ rememberSelection();
220
+ onMouseUp?.(e);
221
+ };
222
+ const handleKeyUp = (e) => {
223
+ rememberSelection();
224
+ onKeyUp?.(e);
225
+ };
226
+ const handleRef = (node) => {
227
+ editorRef.current = node;
228
+ if (typeof ref === "function") {
229
+ ref(node);
230
+ return;
231
+ }
232
+ if (ref) {
233
+ ref.current = node;
74
234
  }
75
- onInput?.(html, e);
76
235
  };
236
+ const getSelection = react.useCallback(() => selectionRef.current?.cloneRange() ?? null, []);
237
+ const controls$1 = react.useMemo(() => controls.default({
238
+ controlBtnProps,
239
+ addtionControls,
240
+ getSelection,
241
+ }), [addtionControls, getSelection]);
77
242
  return (jsxRuntime.jsxs("div", { className: classNames__default("i-editor", className, {
78
243
  "i-editor-borderless": !border,
79
244
  }), style: {
80
245
  ...style,
81
246
  [autosize ? "minHeight" : "height"]: height,
82
247
  width,
83
- }, children: [controls$1 !== "none" && (jsxRuntime.jsx("div", { className: 'i-editor-controls', children: controls.default(controls$1, {
84
- controlBtnProps,
85
- }) })), jsxRuntime.jsx("div", { ref: editorRef, className: 'i-editor-content', "data-placeholder": placeholder, contentEditable: true, onPaste: handlePaste, onInput: handleInput, onKeyDown: handleKeyDown, ...restProps })] }));
248
+ }, children: [!hideControl && (jsxRuntime.jsx("div", { className: "i-editor-controls", children: controls$1 })), memtion$1 && (jsxRuntime.jsx(memtion.default, { visible: memtionVisible, rect: memtionRect, options: memtionOptions, activeIndex: memtionActiveIndex, onActiveChange: setMemtionActiveIndex, onSelect: insertMemtion })), jsxRuntime.jsx("div", { ref: handleRef, className: "i-editor-content", "data-placeholder": placeholder, contentEditable: mode === "plaintext" ? "plaintext-only" : true, onFocus: handleFocus, onBlur: handleBlur, onMouseUp: handleMouseUp, onPaste: handlePaste, onInput: handleInput, onKeyUp: handleKeyUp, onKeyDown: handleKeyDown, ...restProps })] }));
86
249
  };
87
250
 
88
251
  exports.default = Editor;
@@ -1 +1 @@
1
- {"version":3,"file":"editor.js","sources":["../../../../packages/components/editor/editor.tsx"],"sourcesContent":["import classNames from \"classnames\";\r\nimport { useImperativeHandle, useRef } from \"react\";\r\nimport xss from \"xss\";\r\nimport { IButton } from \"../button/type\";\r\nimport getControls, { exec, xssOptions } from \"./controls\";\r\nimport \"./index.css\";\r\nimport { IEditor } from \"./type\";\r\n\r\nconst Editor = (props: IEditor) => {\r\n\tconst {\r\n\t\tref,\r\n\t\twidth,\r\n\t\theight = \"10em\",\r\n\t\tplaceholder,\r\n\t\tautosize,\r\n\t\tborder = true,\r\n\t\trichPaste,\r\n\t\tcontrols = \"simple\",\r\n\t\tclassName,\r\n\t\tstyle,\r\n\t\tonInput,\r\n\t\tonPaste,\r\n\t\tonKeyDown,\r\n\t\t...restProps\r\n\t} = props;\r\n\tconst editorRef = useRef<HTMLDivElement>(null);\r\n\tconst controlBtnProps: IButton = {\r\n\t\tsquare: true,\r\n\t\tflat: true,\r\n\t\tsize: \"small\",\r\n\t};\r\n\r\n\tconst handlePaste = async (e) => {\r\n\t\tonPaste?.(e);\r\n\r\n\t\tif (richPaste) return;\r\n\t\te.preventDefault();\r\n\t\tconst text = e.clipboardData.getData(\"text/plain\");\r\n\t\texec(\"insertText\", false, text);\r\n\t};\r\n\r\n\tconst handleKeyDown = (e) => {\r\n\t\tonKeyDown?.(e);\r\n\r\n\t\tswitch (e.key) {\r\n\t\t\tcase \"Tab\":\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\texec(\"insertHTML\", false, \"&#09;\");\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"Enter\":\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\texec(\"insertLineBreak\");\r\n\r\n\t\t\t\tif (!editorRef.current) return;\r\n\t\t\t\teditorRef.current.scrollBy({\r\n\t\t\t\t\ttop: 20,\r\n\t\t\t\t\tleft: -1000,\r\n\t\t\t\t});\r\n\r\n\t\t\t\tif (!autosize) return;\r\n\t\t\t\teditorRef.current.style.height = `${editorRef.current.scrollHeight}px`;\r\n\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t};\r\n\r\n\tuseImperativeHandle(ref, () => {\r\n\t\treturn {\r\n\t\t\tinput: editorRef.current,\r\n\t\t\tsetValue(html) {\r\n\t\t\t\tif (!editorRef.current) return;\r\n\t\t\t\tconst safeHtml = xss(html, xssOptions);\r\n\r\n\t\t\t\teditorRef.current.innerHTML = safeHtml;\r\n\t\t\t},\r\n\t\t\tgetSafeValue() {\r\n\t\t\t\tconst html = editorRef.current?.innerHTML ?? \"\";\r\n\r\n\t\t\t\treturn xss(html, xssOptions);\r\n\t\t\t},\r\n\t\t};\r\n\t});\r\n\r\n\tconst handleInput = (e) => {\r\n\t\tlet html = editorRef.current?.innerHTML ?? \"\";\r\n\r\n\t\tif ([\"<br>\", \"\\n\"].includes(html) && editorRef.current) {\r\n\t\t\thtml = \"\";\r\n\t\t\teditorRef.current.innerHTML = html;\r\n\t\t}\r\n\r\n\t\tonInput?.(html, e);\r\n\t};\r\n\r\n\treturn (\r\n\t\t<div\r\n\t\t\tclassName={classNames(\"i-editor\", className, {\r\n\t\t\t\t\"i-editor-borderless\": !border,\r\n\t\t\t})}\r\n\t\t\tstyle={{\r\n\t\t\t\t...style,\r\n\t\t\t\t[autosize ? \"minHeight\" : \"height\"]: height,\r\n\t\t\t\twidth,\r\n\t\t\t}}\r\n\t\t>\r\n\t\t\t{controls !== \"none\" && (\r\n\t\t\t\t<div className='i-editor-controls'>\r\n\t\t\t\t\t{getControls(controls, {\r\n\t\t\t\t\t\tcontrolBtnProps,\r\n\t\t\t\t\t})}\r\n\t\t\t\t</div>\r\n\t\t\t)}\r\n\r\n\t\t\t<div\r\n\t\t\t\tref={editorRef}\r\n\t\t\t\tclassName='i-editor-content'\r\n\t\t\t\tdata-placeholder={placeholder}\r\n\t\t\t\tcontentEditable\r\n\t\t\t\tonPaste={handlePaste}\r\n\t\t\t\tonInput={handleInput}\r\n\t\t\t\tonKeyDown={handleKeyDown}\r\n\t\t\t\t{...restProps}\r\n\t\t\t/>\r\n\t\t</div>\r\n\t);\r\n};\r\n\r\nexport default Editor;\r\n"],"names":["controls","useRef","exec","useImperativeHandle","xss","xssOptions","_jsxs","classNames","_jsx","getControls"],"mappings":"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"}
1
+ {"version":3,"file":"editor.js","sources":["../../../../packages/components/editor/editor.tsx"],"sourcesContent":["import classNames from \"classnames\";\r\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\r\nimport xss from \"xss\";\r\nimport { IButton } from \"../button/type\";\r\nimport getControls, { exec, xssOptions } from \"./controls\";\r\nimport \"./index.css\";\r\nimport Memtion, {\r\n filterMemtionOptions,\r\n getMemtionReplaceRange,\r\n getMemtionText,\r\n getSelectionRect,\r\n insertMemtionOption,\r\n removeAdjacentMemtionTag,\r\n} from \"./memtion\";\r\nimport { IEditor, IEditorMemtionOption } from \"./type\";\r\n\r\nconst controlBtnProps: IButton = {\r\n square: true,\r\n flat: true,\r\n size: \"small\",\r\n};\r\n\r\nconst Editor = (props: IEditor) => {\r\n const {\r\n ref,\r\n value = \"\",\r\n width,\r\n height = \"10em\",\r\n placeholder,\r\n autosize,\r\n border = true,\r\n mode = \"rich\",\r\n hideControl,\r\n addtionControls,\r\n memtion,\r\n className,\r\n style,\r\n onChange,\r\n onEnter,\r\n onFocus,\r\n onBlur,\r\n onPaste,\r\n onMouseUp,\r\n onKeyUp,\r\n onKeyDown,\r\n ...restProps\r\n } = props;\r\n const editorRef = useRef<HTMLDivElement>(null);\r\n const selectionRef = useRef<Range | null>(null);\r\n const memtionTriggerRangeRef = useRef<Range | null>(null);\r\n const pendingMemtionRef = useRef(false);\r\n const [memtionVisible, setMemtionVisible] = useState(false);\r\n const [memtionRect, setMemtionRect] = useState<DOMRect | null>(null);\r\n const [memtionKeyword, setMemtionKeyword] = useState(\"\");\r\n const [memtionActiveIndex, setMemtionActiveIndex] = useState(0);\r\n const memtionOptions = useMemo(\r\n () => filterMemtionOptions(memtion?.options ?? [], memtionKeyword),\r\n [memtion?.options, memtionKeyword],\r\n );\r\n\r\n const sanitizeValue = (nextValue: string) => {\r\n if (mode === \"plaintext\") {\r\n return nextValue === \"\\n\" ? \"\" : nextValue;\r\n }\r\n\r\n const safeHtml = xss(nextValue, xssOptions);\r\n\r\n return safeHtml === \"<br>\" ? \"\" : safeHtml;\r\n };\r\n\r\n const rememberSelection = () => {\r\n if (!editorRef.current) return;\r\n\r\n const selection = window.getSelection();\r\n if (!selection?.rangeCount) return;\r\n\r\n const range = selection.getRangeAt(0);\r\n const container = range.commonAncestorContainer;\r\n const parent =\r\n container.nodeType === Node.ELEMENT_NODE\r\n ? (container as Element)\r\n : container.parentElement;\r\n\r\n if (!parent || !editorRef.current.contains(parent)) return;\r\n\r\n selectionRef.current = range.cloneRange();\r\n };\r\n\r\n const setEditorValue = (nextValue: string) => {\r\n if (!editorRef.current) return;\r\n\r\n const safeValue = sanitizeValue(nextValue);\r\n\r\n if (mode === \"plaintext\") {\r\n editorRef.current.textContent = safeValue;\r\n return;\r\n }\r\n\r\n editorRef.current.innerHTML = safeValue;\r\n };\r\n\r\n const getEditorValue = (sanitize = false) => {\r\n if (!editorRef.current) return \"\";\r\n\r\n const nextValue =\r\n mode === \"plaintext\"\r\n ? (editorRef.current.textContent ?? \"\")\r\n : editorRef.current.innerHTML;\r\n\r\n return sanitize ? sanitizeValue(nextValue) : nextValue;\r\n };\r\n\r\n const hideMemtion = () => {\r\n pendingMemtionRef.current = false;\r\n memtionTriggerRangeRef.current = null;\r\n setMemtionVisible(false);\r\n setMemtionRect(null);\r\n setMemtionKeyword(\"\");\r\n setMemtionActiveIndex(0);\r\n };\r\n\r\n const insertMemtion = (option: IEditorMemtionOption) => {\r\n const replaceRange = getMemtionReplaceRange(\r\n memtionTriggerRangeRef.current,\r\n selectionRef.current,\r\n );\r\n\r\n const range = insertMemtionOption({\r\n editor: editorRef.current,\r\n range: replaceRange,\r\n mode,\r\n memtion,\r\n option,\r\n sanitizeValue,\r\n });\r\n\r\n if (!range || !editorRef.current) return;\r\n\r\n selectionRef.current = range.cloneRange();\r\n hideMemtion();\r\n editorRef.current.dispatchEvent(new Event(\"input\", { bubbles: true }));\r\n };\r\n\r\n const handlePaste = (e) => {\r\n onPaste?.(e);\r\n\r\n if (e.defaultPrevented) return;\r\n\r\n e.preventDefault();\r\n\r\n if (mode === \"plaintext\") {\r\n const text = e.clipboardData.getData(\"text/plain\");\r\n exec(\"insertText\", false, text);\r\n return;\r\n }\r\n\r\n const html = e.clipboardData.getData(\"text/html\");\r\n if (html) {\r\n exec(\"insertHTML\", false, sanitizeValue(html));\r\n return;\r\n }\r\n\r\n const text = e.clipboardData.getData(\"text/plain\");\r\n exec(\"insertText\", false, text);\r\n };\r\n\r\n const handleKeyDown = (e) => {\r\n onKeyDown?.(e);\r\n\r\n if (\r\n mode === \"rich\" &&\r\n (e.key === \"Backspace\" || e.key === \"Delete\") &&\r\n removeAdjacentMemtionTag(editorRef.current, e.key)\r\n ) {\r\n e.preventDefault();\r\n rememberSelection();\r\n editorRef.current?.dispatchEvent(\r\n new Event(\"input\", { bubbles: true }),\r\n );\r\n return;\r\n }\r\n\r\n const memtionKey = memtion?.key ?? \"@\";\r\n if (memtionVisible && e.key === \" \") {\r\n hideMemtion();\r\n }\r\n\r\n if (memtionVisible && memtionOptions.length) {\r\n switch (e.key) {\r\n case \"ArrowDown\":\r\n e.preventDefault();\r\n setMemtionActiveIndex((index) =>\r\n index + 1 >= memtionOptions.length ? 0 : index + 1,\r\n );\r\n return;\r\n case \"ArrowUp\":\r\n e.preventDefault();\r\n setMemtionActiveIndex((index) =>\r\n index - 1 < 0 ? memtionOptions.length - 1 : index - 1,\r\n );\r\n return;\r\n case \"Enter\":\r\n e.preventDefault();\r\n insertMemtion(memtionOptions[memtionActiveIndex]);\r\n return;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n if (memtion && e.key === memtionKey) {\r\n rememberSelection();\r\n memtionTriggerRangeRef.current =\r\n selectionRef.current?.cloneRange() ?? null;\r\n pendingMemtionRef.current = true;\r\n }\r\n\r\n switch (e.key) {\r\n case \"Tab\":\r\n e.preventDefault();\r\n exec(\r\n mode === \"plaintext\" ? \"insertText\" : \"insertHTML\",\r\n false,\r\n mode === \"plaintext\" ? \"\\t\" : \"&#09;\",\r\n );\r\n break;\r\n case \"Enter\":\r\n if (!onEnter) break;\r\n e.preventDefault();\r\n onEnter(e);\r\n break;\r\n default:\r\n break;\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n if (!editorRef.current) return;\r\n const nextValue = sanitizeValue(value);\r\n if (getEditorValue(true) === nextValue) return;\r\n\r\n setEditorValue(nextValue);\r\n\r\n if (autosize) {\r\n editorRef.current.style.height = `${editorRef.current.scrollHeight}px`;\r\n }\r\n }, [autosize, mode, value]);\r\n\r\n useEffect(() => {\r\n if (!memtionOptions.length) {\r\n setMemtionActiveIndex(0);\r\n return;\r\n }\r\n\r\n setMemtionActiveIndex((index) =>\r\n index >= memtionOptions.length ? 0 : index,\r\n );\r\n }, [memtionOptions]);\r\n\r\n const handleInput = (e) => {\r\n const rawValue = getEditorValue();\r\n let nextValue = sanitizeValue(rawValue);\r\n\r\n if (!nextValue && rawValue && editorRef.current) {\r\n nextValue = \"\";\r\n setEditorValue(nextValue);\r\n }\r\n\r\n rememberSelection();\r\n\r\n if (memtion && (pendingMemtionRef.current || memtionVisible)) {\r\n const memtionKey = memtion?.key ?? \"@\";\r\n const memtionText = getMemtionText(\r\n memtionTriggerRangeRef.current,\r\n selectionRef.current,\r\n );\r\n\r\n if (!memtionText.startsWith(memtionKey) || /\\s/.test(memtionText)) {\r\n hideMemtion();\r\n } else {\r\n const keyword = memtionText.slice(memtionKey.length);\r\n pendingMemtionRef.current = false;\r\n setMemtionRect(getSelectionRect(selectionRef.current));\r\n setMemtionKeyword(keyword);\r\n setMemtionActiveIndex(0);\r\n setMemtionVisible(true);\r\n }\r\n }\r\n\r\n if (autosize && editorRef.current) {\r\n editorRef.current.style.height = `${editorRef.current.scrollHeight}px`;\r\n }\r\n\r\n onChange?.(nextValue, e);\r\n };\r\n\r\n const handleFocus = (e) => {\r\n rememberSelection();\r\n onFocus?.(e);\r\n };\r\n\r\n const handleBlur = (e) => {\r\n hideMemtion();\r\n onBlur?.(e);\r\n };\r\n\r\n const handleMouseUp = (e) => {\r\n rememberSelection();\r\n onMouseUp?.(e);\r\n };\r\n\r\n const handleKeyUp = (e) => {\r\n rememberSelection();\r\n onKeyUp?.(e);\r\n };\r\n\r\n const handleRef = (node: HTMLDivElement | null) => {\r\n editorRef.current = node;\r\n\r\n if (typeof ref === \"function\") {\r\n ref(node);\r\n return;\r\n }\r\n\r\n if (ref) {\r\n ref.current = node;\r\n }\r\n };\r\n\r\n const getSelection = useCallback(\r\n () => selectionRef.current?.cloneRange() ?? null,\r\n [],\r\n );\r\n\r\n const controls = useMemo(\r\n () =>\r\n getControls({\r\n controlBtnProps,\r\n addtionControls,\r\n getSelection,\r\n }),\r\n [addtionControls, getSelection],\r\n );\r\n\r\n return (\r\n <div\r\n className={classNames(\"i-editor\", className, {\r\n \"i-editor-borderless\": !border,\r\n })}\r\n style={{\r\n ...style,\r\n [autosize ? \"minHeight\" : \"height\"]: height,\r\n width,\r\n }}\r\n >\r\n {!hideControl && (\r\n <div className=\"i-editor-controls\">{controls}</div>\r\n )}\r\n\r\n {memtion && (\r\n <Memtion\r\n visible={memtionVisible}\r\n rect={memtionRect}\r\n options={memtionOptions}\r\n activeIndex={memtionActiveIndex}\r\n onActiveChange={setMemtionActiveIndex}\r\n onSelect={insertMemtion}\r\n />\r\n )}\r\n\r\n <div\r\n ref={handleRef}\r\n className=\"i-editor-content\"\r\n data-placeholder={placeholder}\r\n contentEditable={mode === \"plaintext\" ? \"plaintext-only\" : true}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n onMouseUp={handleMouseUp}\r\n onPaste={handlePaste}\r\n onInput={handleInput}\r\n onKeyUp={handleKeyUp}\r\n onKeyDown={handleKeyDown}\r\n {...restProps}\r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Editor;\r\n"],"names":["memtion","useRef","useState","useMemo","filterMemtionOptions","xss","xssOptions","getMemtionReplaceRange","insertMemtionOption","exec","removeAdjacentMemtionTag","useEffect","getMemtionText","getSelectionRect","useCallback","controls","getControls","_jsxs","classNames","_jsx","Memtion"],"mappings":"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"}