@seafile/sdoc-editor 0.1.150 → 0.1.152

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 (37) hide show
  1. package/dist/api/seafile-api.js +8 -2
  2. package/dist/basic-sdk/assets/css/code-block.css +3 -0
  3. package/dist/basic-sdk/cursor/helper.js +1 -1
  4. package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +30 -3
  5. package/dist/basic-sdk/extension/commons/select-file-dialog/helpers.js +17 -0
  6. package/dist/basic-sdk/extension/{plugins/sdoc-link/dialog/select-sdoc-file-dialog → commons/select-file-dialog}/index.js +39 -4
  7. package/dist/basic-sdk/extension/commons/select-file-dialog/local-files/index.js +174 -0
  8. package/dist/basic-sdk/extension/constants/element-type.js +1 -0
  9. package/dist/basic-sdk/extension/constants/index.js +6 -2
  10. package/dist/basic-sdk/extension/plugins/file-link/constants/index.js +18 -0
  11. package/dist/basic-sdk/extension/plugins/file-link/helpers.js +113 -0
  12. package/dist/basic-sdk/extension/plugins/file-link/hover-menu/index.css +89 -0
  13. package/dist/basic-sdk/extension/plugins/file-link/hover-menu/index.js +113 -0
  14. package/dist/basic-sdk/extension/plugins/file-link/index.js +11 -0
  15. package/dist/basic-sdk/extension/plugins/file-link/menu/index.js +28 -0
  16. package/dist/basic-sdk/extension/plugins/file-link/plugin.js +40 -0
  17. package/dist/basic-sdk/extension/plugins/file-link/render-elem.css +41 -0
  18. package/dist/basic-sdk/extension/plugins/file-link/render-elem.js +141 -0
  19. package/dist/basic-sdk/extension/plugins/index.js +3 -2
  20. package/dist/basic-sdk/extension/plugins/sdoc-link/helpers.js +0 -16
  21. package/dist/basic-sdk/extension/plugins/sdoc-link/menu/index.js +3 -2
  22. package/dist/basic-sdk/extension/plugins/text-style/caret.js +1 -1
  23. package/dist/basic-sdk/extension/render/render-element.js +8 -2
  24. package/dist/basic-sdk/extension/toolbar/header-toolbar/insert-toolbar/index.js +2 -1
  25. package/dist/context.js +8 -2
  26. package/package.json +1 -1
  27. package/public/locales/en/sdoc-editor.json +3 -1
  28. package/public/locales/zh_CN/sdoc-editor.json +1 -0
  29. package/public/media/sdoc-editor-font/iconfont.eot +0 -0
  30. package/public/media/sdoc-editor-font/iconfont.svg +2 -0
  31. package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
  32. package/public/media/sdoc-editor-font/iconfont.woff +0 -0
  33. package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
  34. package/public/media/sdoc-editor-font.css +10 -6
  35. package/dist/basic-sdk/extension/plugins/sdoc-link/dialog/select-sdoc-file-dialog/local-files/index.js +0 -143
  36. /package/dist/basic-sdk/extension/{plugins/sdoc-link/dialog/select-sdoc-file-dialog → commons/select-file-dialog}/index.css +0 -0
  37. /package/dist/basic-sdk/extension/{plugins/sdoc-link/dialog/select-sdoc-file-dialog → commons/select-file-dialog}/local-files/index.css +0 -0
@@ -83,8 +83,14 @@ var SeafileAPI = /*#__PURE__*/function () {
83
83
  }
84
84
  }, {
85
85
  key: "getSdocFiles",
86
- value: function getSdocFiles(docUuid, p) {
87
- var url = 'api/v2.1/seadoc/dir/' + docUuid + '/?p=' + p + '&doc_uuid=' + docUuid;
86
+ value: function getSdocFiles(docUuid, p, type) {
87
+ var url = 'api/v2.1/seadoc/dir/' + docUuid + '/?p=' + p + '&type=' + type + '&doc_uuid=' + docUuid;
88
+ return this.req.get(url);
89
+ }
90
+ }, {
91
+ key: "getSdocFileId",
92
+ value: function getSdocFileId(docUuid, p) {
93
+ var url = 'api/v2.1/seadoc/file-uuid/' + docUuid + '/?p=' + p;
88
94
  return this.req.get(url);
89
95
  }
90
96
  }, {
@@ -25,6 +25,9 @@
25
25
  color: #ccc;
26
26
  display: inline-block;
27
27
  width: 40px;
28
+ text-align: end;
29
+ margin-left: -16px;
30
+ margin-right: 20px;
28
31
  }
29
32
 
30
33
  .sdoc-code-line
@@ -32,6 +32,6 @@ export var generateCursorData = function generateCursorData(config) {
32
32
  var color = randomColor(options);
33
33
  return {
34
34
  name: user.name,
35
- color: color
35
+ cursor_color: color
36
36
  };
37
37
  };
@@ -2,7 +2,7 @@ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
2
  import React, { useCallback, useEffect, useState, useRef } from 'react';
3
3
  import CustomTableSizeDialog from '../../plugins/table/dialog/custom-table-size-dialog';
4
4
  import AddLinkDialog from '../../plugins/link/dialog/add-link-dialog';
5
- import SelectSdocFileDialog from '../../plugins/sdoc-link/dialog/select-sdoc-file-dialog';
5
+ import SelectFileDialog from '../select-file-dialog/index.js';
6
6
  import EventBus from '../../../utils/event-bus';
7
7
  import { INTERNAL_EVENT } from '../../../constants';
8
8
  import { ELEMENT_TYPE, INSERT_POSITION, LOCAL_IMAGE } from '../../constants';
@@ -26,6 +26,10 @@ var InsertElementDialog = function InsertElementDialog(_ref) {
26
26
  _useState8 = _slicedToArray(_useState7, 2),
27
27
  slateNode = _useState8[0],
28
28
  setSlateNode = _useState8[1];
29
+ var _useState9 = useState(null),
30
+ _useState10 = _slicedToArray(_useState9, 2),
31
+ insertLinkCallback = _useState10[0],
32
+ setInsertLinkCallback = _useState10[1];
29
33
  var uploadLocalImageInputRef = useRef();
30
34
  var onFileChanged = useCallback(function (event) {
31
35
  var file = event.target.files[0];
@@ -51,11 +55,17 @@ var InsertElementDialog = function InsertElementDialog(_ref) {
51
55
  element = _ref2.element,
52
56
  _ref2$insertPosition = _ref2.insertPosition,
53
57
  insertPosition = _ref2$insertPosition === void 0 ? INSERT_POSITION.CURRENT : _ref2$insertPosition,
54
- slateNode = _ref2.slateNode;
58
+ slateNode = _ref2.slateNode,
59
+ insertFileLinkCallback = _ref2.insertFileLinkCallback,
60
+ insertSdocFileLinkCallback = _ref2.insertSdocFileLinkCallback;
55
61
  setInsertPosition(insertPosition);
56
62
  setSlateNode(slateNode);
57
63
  setElement(element);
58
64
  setDialogType(type);
65
+ setInsertLinkCallback({
66
+ insertSdocFileLinkCallback: insertSdocFileLinkCallback,
67
+ insertFileLinkCallback: insertFileLinkCallback
68
+ });
59
69
  if (type === LOCAL_IMAGE) {
60
70
  setTimeout(function () {
61
71
  uploadLocalImageInputRef.current && uploadLocalImageInputRef.current.click();
@@ -67,6 +77,7 @@ var InsertElementDialog = function InsertElementDialog(_ref) {
67
77
  setSlateNode(null);
68
78
  setElement('');
69
79
  setDialogType('');
80
+ setInsertLinkCallback(null);
70
81
  }, []);
71
82
  var props = {
72
83
  insertPosition: insertPosition,
@@ -86,7 +97,23 @@ var InsertElementDialog = function InsertElementDialog(_ref) {
86
97
  }
87
98
  case ELEMENT_TYPE.SDOC_LINK:
88
99
  {
89
- return /*#__PURE__*/React.createElement(SelectSdocFileDialog, props);
100
+ var sdocLinkProps = {
101
+ editor: editor,
102
+ dialogType: dialogType,
103
+ insertLinkCallback: insertLinkCallback,
104
+ closeDialog: closeDialog
105
+ };
106
+ return /*#__PURE__*/React.createElement(SelectFileDialog, sdocLinkProps);
107
+ }
108
+ case ELEMENT_TYPE.FILE_LINK:
109
+ {
110
+ var fileLinkProps = {
111
+ editor: editor,
112
+ dialogType: dialogType,
113
+ insertLinkCallback: insertLinkCallback,
114
+ closeDialog: closeDialog
115
+ };
116
+ return /*#__PURE__*/React.createElement(SelectFileDialog, fileLinkProps);
90
117
  }
91
118
  case LOCAL_IMAGE:
92
119
  {
@@ -0,0 +1,17 @@
1
+ export var addDataToTree = function addDataToTree(treeData, indexId, childrenData, path) {
2
+ for (var i = 0; i < treeData.length; i++) {
3
+ var _treeData$i;
4
+ if (treeData[i].indexId === indexId) {
5
+ treeData[i].children = childrenData;
6
+ treeData[i].children.forEach(function (child) {
7
+ child.path = path + "/".concat(child.name);
8
+ });
9
+ break;
10
+ }
11
+ if ((_treeData$i = treeData[i]) === null || _treeData$i === void 0 ? void 0 : _treeData$i.children) {
12
+ var _treeData$i2;
13
+ addDataToTree((_treeData$i2 = treeData[i]) === null || _treeData$i2 === void 0 ? void 0 : _treeData$i2.children, indexId, childrenData, path);
14
+ }
15
+ }
16
+ return treeData;
17
+ };
@@ -1,13 +1,20 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
1
2
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
3
  import React, { useCallback, useState } from 'react';
3
4
  import { Button, Modal, ModalHeader, ModalBody } from 'reactstrap';
4
5
  import { useTranslation } from 'react-i18next';
6
+ import context from '../../../../context';
5
7
  import LocalFiles from './local-files';
6
- import { insertSdocFileLink } from '../../helpers';
8
+ import toaster from '../../../../components/toast';
9
+ import { getErrorMsg } from '../../../../utils/';
7
10
  import './index.css';
8
11
  var SelectSdocFileDialog = function SelectSdocFileDialog(_ref) {
9
12
  var editor = _ref.editor,
10
- closeDialog = _ref.closeDialog;
13
+ dialogType = _ref.dialogType,
14
+ closeDialog = _ref.closeDialog,
15
+ insertLinkCallback = _ref.insertLinkCallback;
16
+ var type = dialogType === 'file-link' ? 'file' : 'sdoc';
17
+ var modalTitle = dialogType === 'file-link' ? 'Select_file' : 'Select_sdoc_document';
11
18
  var _useTranslation = useTranslation(),
12
19
  t = _useTranslation.t;
13
20
  var _useState = useState(null),
@@ -17,9 +24,36 @@ var SelectSdocFileDialog = function SelectSdocFileDialog(_ref) {
17
24
  var onSelectedFile = useCallback(function (fileInfo) {
18
25
  setCurrentSelectedFile(fileInfo);
19
26
  }, []);
27
+ var insertFile = useCallback(function (fileInfo) {
28
+ var insertFileLinkCallback = insertLinkCallback.insertFileLinkCallback,
29
+ insertSdocFileLinkCallback = insertLinkCallback.insertSdocFileLinkCallback;
30
+ if (dialogType === 'file-link') {
31
+ insertFileLinkCallback && insertFileLinkCallback(editor, fileInfo.name, fileInfo.file_uuid);
32
+ } else {
33
+ insertSdocFileLinkCallback && insertSdocFileLinkCallback(editor, fileInfo.name, fileInfo.file_uuid);
34
+ }
35
+ }, [insertLinkCallback, dialogType, editor]);
20
36
  var onSubmit = useCallback(function () {
21
37
  if (!currentSelectedFile) return;
22
- insertSdocFileLink(editor, currentSelectedFile.name, currentSelectedFile.doc_uuid);
38
+ var file_uuid = currentSelectedFile.file_uuid;
39
+ var fileInfo = _objectSpread({}, currentSelectedFile);
40
+ // File has no id
41
+ if (!file_uuid || file_uuid === '') {
42
+ context.getSdocLocalFileId(currentSelectedFile.path).then(function (res) {
43
+ if (res.status === 200) {
44
+ fileInfo = _objectSpread(_objectSpread({}, currentSelectedFile), {}, {
45
+ file_uuid: res.data.file_uuid
46
+ });
47
+ }
48
+ insertFile(fileInfo);
49
+ closeDialog();
50
+ }).catch(function (error) {
51
+ var errorMessage = getErrorMsg(error);
52
+ toaster.danger(errorMessage);
53
+ });
54
+ return;
55
+ }
56
+ insertFile(fileInfo);
23
57
  closeDialog();
24
58
  // eslint-disable-next-line react-hooks/exhaustive-deps
25
59
  }, [currentSelectedFile]);
@@ -32,7 +66,7 @@ var SelectSdocFileDialog = function SelectSdocFileDialog(_ref) {
32
66
  contentClassName: "sdoc-file-select-modal"
33
67
  }, /*#__PURE__*/React.createElement(ModalHeader, {
34
68
  toggle: closeDialog
35
- }, t('Select_sdoc_document')), /*#__PURE__*/React.createElement(ModalBody, {
69
+ }, t(modalTitle)), /*#__PURE__*/React.createElement(ModalBody, {
36
70
  className: "p-0"
37
71
  }, /*#__PURE__*/React.createElement("div", {
38
72
  className: "sdoc-file-select-container"
@@ -45,6 +79,7 @@ var SelectSdocFileDialog = function SelectSdocFileDialog(_ref) {
45
79
  }, t('Local_file')))), /*#__PURE__*/React.createElement("div", {
46
80
  className: "sdoc-file-select-right"
47
81
  }, /*#__PURE__*/React.createElement(LocalFiles, {
82
+ type: type,
48
83
  onSelectedFile: onSelectedFile,
49
84
  toggle: closeDialog
50
85
  }), /*#__PURE__*/React.createElement("div", {
@@ -0,0 +1,174 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
2
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
3
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
+ function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(typeof e + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
5
+ import React, { useCallback, useState, useRef, useEffect } from 'react';
6
+ import { withTranslation } from 'react-i18next';
7
+ import classnames from 'classnames';
8
+ import slugid from 'slugid';
9
+ import context from '../../../../../context';
10
+ import { getErrorMsg } from '../../../../../utils/';
11
+ import toaster from '../../../../../components/toast';
12
+ import { addDataToTree } from '../helpers';
13
+ import './index.css';
14
+ var LocalFiles = function LocalFiles(_ref) {
15
+ var onSelectedFile = _ref.onSelectedFile,
16
+ toggle = _ref.toggle,
17
+ fileType = _ref.type,
18
+ t = _ref.t;
19
+ var folderRef = useRef(null);
20
+ var _useState = useState(new Set([])),
21
+ _useState2 = _slicedToArray(_useState, 2),
22
+ expandedFolder = _useState2[0],
23
+ setExpandedFolder = _useState2[1];
24
+ var _useState3 = useState(null),
25
+ _useState4 = _slicedToArray(_useState3, 2),
26
+ currentActiveItem = _useState4[0],
27
+ setCurrentActiveItem = _useState4[1];
28
+ var _useState5 = useState([]),
29
+ _useState6 = _slicedToArray(_useState5, 2),
30
+ treeData = _useState6[0],
31
+ setTreeData = _useState6[1];
32
+ var collapsedFolder = useCallback(function (data, indexId) {
33
+ for (var i = 0; i < data.length; i++) {
34
+ var _data$i;
35
+ if (data[i].indexId === indexId) {
36
+ data[i].children = null;
37
+ break;
38
+ }
39
+ if ((_data$i = data[i]) === null || _data$i === void 0 ? void 0 : _data$i.children) {
40
+ collapsedFolder(data[i].children, indexId);
41
+ }
42
+ }
43
+ setTreeData(_toConsumableArray(data));
44
+ // eslint-disable-next-line react-hooks/exhaustive-deps
45
+ }, []);
46
+ var getTreeData = useCallback(function (p, indexId, treeData) {
47
+ return context.getSdocLocalFiles(p, fileType).then(function (res) {
48
+ res.data.forEach(function (item) {
49
+ item.indexId = slugid.nice();
50
+ });
51
+ // Open folder
52
+ if (indexId && treeData.length > 0) {
53
+ var newFileListData = addDataToTree(treeData, indexId, res.data, p);
54
+ setTreeData(_toConsumableArray(newFileListData));
55
+ return;
56
+ }
57
+ // First loads
58
+ res.data.forEach(function (item) {
59
+ item.path = "/".concat(item.name);
60
+ });
61
+ setTreeData(res.data);
62
+ }).catch(function (error) {
63
+ toggle();
64
+ var errorMessage = getErrorMsg(error);
65
+ toaster.danger(errorMessage);
66
+ });
67
+ // eslint-disable-next-line react-hooks/exhaustive-deps
68
+ }, []);
69
+ useEffect(function () {
70
+ var rootPath = '/';
71
+ getTreeData(rootPath);
72
+ // eslint-disable-next-line react-hooks/exhaustive-deps
73
+ }, []);
74
+ var onToggle = useCallback( /*#__PURE__*/function () {
75
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(e, item, treeData) {
76
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
77
+ while (1) switch (_context.prev = _context.next) {
78
+ case 0:
79
+ e.stopPropagation();
80
+ if (!expandedFolder.has(item.indexId)) {
81
+ _context.next = 6;
82
+ break;
83
+ }
84
+ collapsedFolder(treeData, item.indexId);
85
+ expandedFolder.delete(item.indexId);
86
+ _context.next = 9;
87
+ break;
88
+ case 6:
89
+ _context.next = 8;
90
+ return getTreeData(item.path, item.indexId, treeData);
91
+ case 8:
92
+ expandedFolder.add(item.indexId);
93
+ case 9:
94
+ onSelectedFile(null);
95
+ setCurrentActiveItem(item);
96
+ setExpandedFolder(new Set(Array.from(expandedFolder)));
97
+ // eslint-disable-next-line react-hooks/exhaustive-deps
98
+ case 12:
99
+ case "end":
100
+ return _context.stop();
101
+ }
102
+ }, _callee);
103
+ }));
104
+ return function (_x, _x2, _x3) {
105
+ return _ref2.apply(this, arguments);
106
+ };
107
+ }(), [expandedFolder]);
108
+ var onSelectFile = useCallback(function (e, file) {
109
+ e.stopPropagation();
110
+ setCurrentActiveItem(file);
111
+ onSelectedFile(file);
112
+ // eslint-disable-next-line react-hooks/exhaustive-deps
113
+ }, []);
114
+ var renderFileTree = useCallback(function (data) {
115
+ if (!Array.isArray(data) || data.length === 0) return null;
116
+ return data.map(function (item) {
117
+ var _item$children, _item$children2;
118
+ if (!item) return null;
119
+ var type = item.type,
120
+ indexId = item.indexId,
121
+ name = item.name;
122
+ var selected = (currentActiveItem === null || currentActiveItem === void 0 ? void 0 : currentActiveItem.indexId) === indexId;
123
+ return /*#__PURE__*/React.createElement("div", {
124
+ key: indexId,
125
+ className: "sdoc-folder-container"
126
+ }, type === 'dir' && /*#__PURE__*/React.createElement("div", {
127
+ ref: folderRef,
128
+ className: "sdoc-folder"
129
+ }, /*#__PURE__*/React.createElement("div", {
130
+ className: classnames('sdoc-folder-info sdoc-file-info', {
131
+ 'active': selected,
132
+ 'expanded': expandedFolder.has(indexId)
133
+ }),
134
+ onClick: function onClick(e) {
135
+ return onToggle(e, item, treeData);
136
+ }
137
+ }, /*#__PURE__*/React.createElement("div", {
138
+ className: "sdoc-file-icon-container"
139
+ }, /*#__PURE__*/React.createElement("i", {
140
+ className: "sdoc-file-icon sdoc-file-icon-toggle sdocfont sdoc-right-slide"
141
+ }), /*#__PURE__*/React.createElement("i", {
142
+ className: "sdoc-file-icon sdocfont sdoc-file sdoc-folder-icon"
143
+ })), /*#__PURE__*/React.createElement("span", {
144
+ className: "sdoc-folder-name sdoc-file-name"
145
+ }, name)), /*#__PURE__*/React.createElement("div", {
146
+ className: "sdoc-folder-children"
147
+ }, ((_item$children = item.children) === null || _item$children === void 0 ? void 0 : _item$children.length) === 0 && /*#__PURE__*/React.createElement("div", {
148
+ className: "sdoc-folder-children-empty"
149
+ }, "(".concat(t('Empty'), ")")), ((_item$children2 = item.children) === null || _item$children2 === void 0 ? void 0 : _item$children2.length) > 0 && renderFileTree(item.children))), type === 'file' && /*#__PURE__*/React.createElement("div", {
150
+ className: classnames('sdoc-file-info', {
151
+ 'active': selected
152
+ }),
153
+ onClick: function onClick(e) {
154
+ onSelectFile(e, item);
155
+ }
156
+ }, /*#__PURE__*/React.createElement("div", {
157
+ className: "sdoc-file-icon-container"
158
+ }, /*#__PURE__*/React.createElement("i", {
159
+ className: classnames('sdoc-file-icon sdocfont', {
160
+ 'sdoc-document': fileType === 'sdoc'
161
+ }, {
162
+ 'sdoc-link-file': fileType === 'file'
163
+ })
164
+ })), /*#__PURE__*/React.createElement("span", {
165
+ className: "sdoc-file-name"
166
+ }, name)));
167
+ });
168
+ // eslint-disable-next-line react-hooks/exhaustive-deps
169
+ }, [treeData, currentActiveItem, expandedFolder]);
170
+ return /*#__PURE__*/React.createElement("div", {
171
+ className: "sdoc-files-tree"
172
+ }, renderFileTree(treeData));
173
+ };
174
+ export default withTranslation('sdoc-editor')(LocalFiles);
@@ -42,6 +42,7 @@ export var ALIGN_RIGHT = 'align-right';
42
42
  export var ALIGN_CENTER = 'align-center';
43
43
  export var CLEAR_FORMAT = 'clear-format';
44
44
  export var SDOC_LINK = 'sdoc-link';
45
+ export var FILE_LINK = 'file-link';
45
46
 
46
47
  // font
47
48
  export var FONT_SIZE = 'font-size';
@@ -2,7 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
2
  var _MENUS_CONFIG_MAP, _HEADER_TITLE_MAP;
3
3
  // extension plugin
4
4
  import * as ELEMENT_TYPE from './element-type';
5
- import { BLOCKQUOTE, HEADER, TITLE, SUBTITLE, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, SUPERSCRIPT, SUBSCRIPT, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, LIST_LIC, CHECK_LIST, CHECK_LIST_ITEM, LINK, HTML, CODE_BLOCK, CODE_LINE, IMAGE, TABLE, TABLE_CELL, TABLE_ROW, FORMULA, COLUMN, TEXT_STYLE, TEXT_STYLE_MORE, BOLD_ITALIC, TEXT_ALIGN, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, CLEAR_FORMAT, COLOR, HIGHLIGHT_COLOR, SDOC_LINK } from './element-type';
5
+ import { BLOCKQUOTE, HEADER, TITLE, SUBTITLE, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, SUPERSCRIPT, SUBSCRIPT, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, LIST_LIC, CHECK_LIST, CHECK_LIST_ITEM, LINK, HTML, CODE_BLOCK, CODE_LINE, IMAGE, TABLE, TABLE_CELL, TABLE_ROW, FORMULA, COLUMN, TEXT_STYLE, TEXT_STYLE_MORE, BOLD_ITALIC, TEXT_ALIGN, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, CLEAR_FORMAT, COLOR, HIGHLIGHT_COLOR, SDOC_LINK, FILE_LINK } from './element-type';
6
6
  import { KEYBOARD, MAC_HOTKEYS, WIN_HOTKEYS } from './keyboard';
7
7
  import { DEFAULT_COLORS, STANDARD_COLORS, DEFAULT_RECENT_USED_LIST, DEFAULT_FONT_COLOR, RECENT_USED_HIGHLIGHT_COLORS_KEY, RECENT_USED_FONT_COLORS_KEY, RECENT_USED_TABLE_CELL_BG_COLORS_KEY, DEFAULT_LAST_USED_FONT_COLOR, DEFAULT_LAST_USED_HIGHLIGHT_COLOR, DEFAULT_LAST_USED_TABLE_CELL_BG_COLOR } from './color';
8
8
  import { FONT_SIZE, DEFAULT_FONT, FONT, GOOGLE_FONT_CLASS, RECENT_USED_FONTS_KEY, SDOC_FONT_SIZE } from './font';
@@ -135,6 +135,10 @@ export var MENUS_CONFIG_MAP = (_MENUS_CONFIG_MAP = {}, _defineProperty(_MENUS_CO
135
135
  id: "sdoc_".concat(SDOC_LINK),
136
136
  iconClass: 'sdocfont sdoc-document',
137
137
  text: 'Link_sdoc'
138
+ }), _defineProperty(_MENUS_CONFIG_MAP, FILE_LINK, {
139
+ id: "sdoc_".concat(FILE_LINK),
140
+ iconClass: 'sdocfont sdoc-link-file',
141
+ text: 'Link_file'
138
142
  }), _MENUS_CONFIG_MAP);
139
143
  export var HEADERS = [HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6];
140
144
  export var HEADER_TITLE_MAP = (_HEADER_TITLE_MAP = {}, _defineProperty(_HEADER_TITLE_MAP, TITLE, 'Title'), _defineProperty(_HEADER_TITLE_MAP, SUBTITLE, 'Subtitle'), _defineProperty(_HEADER_TITLE_MAP, HEADER1, 'Header_one'), _defineProperty(_HEADER_TITLE_MAP, HEADER2, 'Header_two'), _defineProperty(_HEADER_TITLE_MAP, HEADER3, 'Header_three'), _defineProperty(_HEADER_TITLE_MAP, HEADER4, 'Header_four'), _defineProperty(_HEADER_TITLE_MAP, HEADER5, 'Header_five'), _defineProperty(_HEADER_TITLE_MAP, HEADER6, 'Header_six'), _defineProperty(_HEADER_TITLE_MAP, PARAGRAPH, 'Paragraph'), _HEADER_TITLE_MAP);
@@ -239,4 +243,4 @@ export var INSERT_POSITION = {
239
243
  export var LOCAL_IMAGE = 'local-image';
240
244
  export var LIST_ITEM_CORRELATION_TYPE = ['unordered_list', 'ordered_list', 'list-item'];
241
245
  export var LIST_ITEM_SUPPORTED_TRANSFORMATION = ['unordered_list', 'ordered_list', 'left', 'center', 'right', 'blockquote'];
242
- export { BLOCKQUOTE, HEADER, TITLE, SUBTITLE, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, SUPERSCRIPT, SUBSCRIPT, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, LIST_LIC, CHECK_LIST, CHECK_LIST_ITEM, LINK, HTML, CODE_BLOCK, CODE_LINE, IMAGE, TABLE, TABLE_CELL, TABLE_ROW, FORMULA, COLUMN, TEXT_STYLE, TEXT_STYLE_MORE, BOLD_ITALIC, TEXT_ALIGN, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ELEMENT_TYPE, KEYBOARD, MAC_HOTKEYS, WIN_HOTKEYS, DEFAULT_COLORS, STANDARD_COLORS, DEFAULT_RECENT_USED_LIST, CLEAR_FORMAT, DEFAULT_FONT_COLOR, RECENT_USED_HIGHLIGHT_COLORS_KEY, RECENT_USED_FONT_COLORS_KEY, RECENT_USED_TABLE_CELL_BG_COLORS_KEY, DEFAULT_LAST_USED_FONT_COLOR, DEFAULT_LAST_USED_HIGHLIGHT_COLOR, DEFAULT_LAST_USED_TABLE_CELL_BG_COLOR, FONT_SIZE, DEFAULT_FONT, FONT, GOOGLE_FONT_CLASS, RECENT_USED_FONTS_KEY, SDOC_FONT_SIZE, SDOC_LINK };
246
+ export { BLOCKQUOTE, HEADER, TITLE, SUBTITLE, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, SUPERSCRIPT, SUBSCRIPT, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, LIST_LIC, CHECK_LIST, CHECK_LIST_ITEM, LINK, HTML, CODE_BLOCK, CODE_LINE, IMAGE, TABLE, TABLE_CELL, TABLE_ROW, FORMULA, COLUMN, TEXT_STYLE, TEXT_STYLE_MORE, BOLD_ITALIC, TEXT_ALIGN, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ELEMENT_TYPE, KEYBOARD, MAC_HOTKEYS, WIN_HOTKEYS, DEFAULT_COLORS, STANDARD_COLORS, DEFAULT_RECENT_USED_LIST, CLEAR_FORMAT, DEFAULT_FONT_COLOR, RECENT_USED_HIGHLIGHT_COLORS_KEY, RECENT_USED_FONT_COLORS_KEY, RECENT_USED_TABLE_CELL_BG_COLORS_KEY, DEFAULT_LAST_USED_FONT_COLOR, DEFAULT_LAST_USED_HIGHLIGHT_COLOR, DEFAULT_LAST_USED_TABLE_CELL_BG_COLOR, FONT_SIZE, DEFAULT_FONT, FONT, GOOGLE_FONT_CLASS, RECENT_USED_FONTS_KEY, SDOC_FONT_SIZE, SDOC_LINK, FILE_LINK };
@@ -0,0 +1,18 @@
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
+ var _FILE_LINK_TYPE_CONFI;
3
+ export var FILE_LINK_TYPE = {
4
+ TEXT_LINK: 'text_link',
5
+ ICON_LINK: 'icon_link',
6
+ CARD_LINK: 'card_link'
7
+ };
8
+ export var FILE_LINK_TYPE_CONFIG = (_FILE_LINK_TYPE_CONFI = {}, _defineProperty(_FILE_LINK_TYPE_CONFI, FILE_LINK_TYPE.TEXT_LINK, {
9
+ icon: 'sdocfont sdoc-text-link',
10
+ text: 'Text_link'
11
+ }), _defineProperty(_FILE_LINK_TYPE_CONFI, FILE_LINK_TYPE.ICON_LINK, {
12
+ icon: 'sdocfont sdoc-inline-link',
13
+ text: 'Icon_and_text_Link'
14
+ }), _defineProperty(_FILE_LINK_TYPE_CONFI, FILE_LINK_TYPE.CARD_LINK, {
15
+ icon: 'sdocfont sdoc-card-link',
16
+ text: 'Card'
17
+ }), _FILE_LINK_TYPE_CONFI);
18
+ export var FILE_LINK_TYPES = [FILE_LINK_TYPE.TEXT_LINK, FILE_LINK_TYPE.ICON_LINK, FILE_LINK_TYPE.CARD_LINK];
@@ -0,0 +1,113 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import { ReactEditor } from '@seafile/slate-react';
3
+ import { Editor, Transforms, Range } from '@seafile/slate';
4
+ import slugid from 'slugid';
5
+ import copy from 'copy-to-clipboard';
6
+ import context from '../../../../context';
7
+ import { FILE_LINK, INSERT_FILE_DISPLAY_TYPE, CODE_BLOCK, CODE_LINE, LINK, PARAGRAPH } from '../../constants';
8
+ import { getNodeType, getSelectedElems } from '../../core';
9
+ export var isMenuDisabled = function isMenuDisabled(editor, readonly) {
10
+ if (readonly) return true;
11
+ if (editor.selection == null) return true;
12
+ var selectedElems = getSelectedElems(editor);
13
+ var notMatch = selectedElems.some(function (elem) {
14
+ var type = elem.type;
15
+ if (editor.isVoid(elem)) return true;
16
+ if ([CODE_BLOCK, CODE_LINE, LINK].includes(type)) return true;
17
+ return false;
18
+ });
19
+ if (notMatch) return true; // disabled
20
+ return false; // enable
21
+ };
22
+
23
+ export var generateFileNode = function generateFileNode(uuid, text) {
24
+ var fileNode = {
25
+ id: slugid.nice(),
26
+ type: FILE_LINK,
27
+ doc_uuid: uuid,
28
+ title: text,
29
+ display_type: INSERT_FILE_DISPLAY_TYPE[0],
30
+ children: [{
31
+ id: slugid.nice(),
32
+ text: text || ''
33
+ }]
34
+ };
35
+ return fileNode;
36
+ };
37
+ export var getType = function getType(editor) {
38
+ var _Editor$nodes = Editor.nodes(editor, {
39
+ match: function match(n) {
40
+ return getNodeType(n) === FILE_LINK;
41
+ },
42
+ universal: true
43
+ }),
44
+ _Editor$nodes2 = _slicedToArray(_Editor$nodes, 1),
45
+ match = _Editor$nodes2[0];
46
+ if (!match) return PARAGRAPH;
47
+ var _match = _slicedToArray(match, 1),
48
+ n = _match[0];
49
+ return getNodeType(n);
50
+ };
51
+ export var insertFileLink = function insertFileLink(editor, text, uuid) {
52
+ if (isMenuDisabled(editor)) return;
53
+
54
+ // Selection folded or not
55
+ var selection = editor.selection;
56
+ if (selection == null) return;
57
+ var isCollapsed = Range.isCollapsed(selection);
58
+ if (isCollapsed) {
59
+ // Insert Spaces before and after filelinks for easy operation
60
+ editor.insertText(' ');
61
+ var fileNode = generateFileNode(uuid, text);
62
+ Transforms.insertNodes(editor, fileNode);
63
+
64
+ // Not being able to use insertText directly causes the added Spaces to be added to the linked text, as in the issue above, replaced by insertFragment
65
+ editor.insertFragment([{
66
+ id: slugid.nice(),
67
+ text: ' '
68
+ }]);
69
+ } else {
70
+ var selectedText = Editor.string(editor, selection); // Selected text
71
+ if (selectedText !== text) {
72
+ // If the selected text is different from the typed text, delete the text and insert the link
73
+ editor.deleteFragment();
74
+ var _fileNode = generateFileNode(uuid, text);
75
+ Transforms.insertNodes(editor, _fileNode);
76
+ } else {
77
+ // If the selected text is the same as the entered text, only the link can be wrapped
78
+ var _fileNode2 = generateFileNode(uuid, text);
79
+ Transforms.wrapNodes(editor, _fileNode2, {
80
+ split: true
81
+ });
82
+ Transforms.collapse(editor, {
83
+ edge: 'end'
84
+ });
85
+ }
86
+ }
87
+ };
88
+ export var unwrapLinkNode = function unwrapLinkNode(editor, element) {
89
+ if (editor.selection == null) return;
90
+ var path = ReactEditor.findPath(editor, element);
91
+ if (path) {
92
+ Transforms.unwrapNodes(editor, {
93
+ at: path
94
+ });
95
+ }
96
+ };
97
+ export var getUrl = function getUrl(uuid) {
98
+ return context.getSdocLocalFileUrl(uuid);
99
+ };
100
+ export var onCopyFileLinkNode = function onCopyFileLinkNode(editor, element) {
101
+ if (editor.selection == null || Range.isExpanded(editor.selection)) return;
102
+ var p = ReactEditor.findPath(editor, element);
103
+ Transforms.select(editor, p);
104
+ var newData = editor.setFragmentData(new DataTransfer());
105
+ copy('copy', {
106
+ onCopy: function onCopy(clipboardData) {
107
+ newData.types.forEach(function (type) {
108
+ var data = newData.getData(type);
109
+ clipboardData.setData(type, data);
110
+ });
111
+ }
112
+ });
113
+ };
@@ -0,0 +1,89 @@
1
+ .sdoc-file-link-hover-menu-container {
2
+ position: absolute;
3
+ height: 42px;
4
+ z-index: 101;
5
+ width: auto;
6
+ }
7
+
8
+ .sdoc-file-link-hover-menu-container .hover-menu-container {
9
+ height: 36px;
10
+ padding: 7px 8px;
11
+ background-color: #fff;
12
+ display: flex;
13
+ justify-content: flex-start;
14
+ align-items: center;
15
+ border-radius: 3px;
16
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
17
+ border: 1px solid #e8e8e8;
18
+ }
19
+
20
+ .sdoc-file-link-hover-menu-container .hover-menu-container > span:not(:last-of-type) {
21
+ padding-right: 8px;
22
+ border-right: 1px solid #e5e5e5;
23
+ }
24
+
25
+ .sdoc-file-link-hover-menu-container .hover-menu-container .op-item {
26
+ position: relative;
27
+ font-size: 12px;
28
+ color: #212529;
29
+ padding: 0 5px;
30
+ border-radius: 2px;
31
+ min-width: 24px;
32
+ height: 24px;
33
+ display: inline-flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ }
37
+
38
+ .sdoc-file-link-hover-menu-container .hover-menu-container .op-item:hover {
39
+ color: #212529;
40
+ text-decoration: none;
41
+ background: #f1f1f1;
42
+ }
43
+
44
+ .sdoc-file-link-hover-menu-container .op-group-item:last-child .op-item {
45
+ margin-left: 8px;
46
+ }
47
+
48
+ .sdoc-file-link-hover-menu-container .hover-menu-container .link-style-icon-active {
49
+ background: #f1f1f1;
50
+ }
51
+
52
+ .sdoc-file-link-hover-menu-container .hover-menu-container .op-tooltip:hover::after {
53
+ position: absolute;
54
+ color: #212529;
55
+ content: attr(op-item-tooltip);
56
+ top: -40px;
57
+ left: -20px;
58
+ width: 70px;
59
+ height: 30px;
60
+ display: flex;
61
+ justify-content: center;
62
+ align-items: center;
63
+ background-color: #fff;
64
+ border-radius: 3px;
65
+ border: 1px solid #e8e8e8;
66
+ font-size: 12px;
67
+ box-shadow: 0 0 5px #ccc;
68
+ }
69
+
70
+ .sdoc-file-link-hover-menu-container .hover-menu-container .icon-font {
71
+ font-size: 12px;
72
+ color: #999999;
73
+ }
74
+
75
+ .sdoc-file-link-hover-menu-container .sdoc-file-display-style-popover {
76
+ position: absolute;
77
+ top: 37px;
78
+ right: -80px;
79
+ padding: 8px 0;
80
+ background-color: #fff;
81
+ border: 1px solid #e5e6e8;
82
+ border-radius: 2px;
83
+ box-shadow: 0 0 10px #ccc;
84
+ display: flex;
85
+ flex-direction: column;
86
+ align-items: flex-start;
87
+ z-index: 101;
88
+ white-space: nowrap;
89
+ }