@lingxiteam/lcdp-ueditor-react 1.0.3-alpha.8 → 1.0.4-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/es/LcdpUeditor.d.ts +10 -4
  2. package/es/LcdpUeditor.d.ts.map +1 -0
  3. package/es/LcdpUeditor.js +77 -11
  4. package/es/ToolBottomBar/FormatModal/index.d.ts +9 -0
  5. package/es/ToolBottomBar/FormatModal/index.d.ts.map +1 -0
  6. package/es/ToolBottomBar/FormatModal/index.js +543 -0
  7. package/es/ToolBottomBar/FormatModal/index.less +276 -0
  8. package/es/ToolBottomBar/ProgressModal/index.d.ts +10 -0
  9. package/es/ToolBottomBar/ProgressModal/index.d.ts.map +1 -0
  10. package/es/ToolBottomBar/ProgressModal/index.js +53 -0
  11. package/es/ToolBottomBar/ProgressModal/index.less +16 -0
  12. package/es/ToolBottomBar/index.d.ts +33 -0
  13. package/es/ToolBottomBar/index.d.ts.map +1 -0
  14. package/es/ToolBottomBar/index.js +296 -0
  15. package/es/ToolBottomBar/index.less +75 -0
  16. package/es/const.d.ts.map +1 -0
  17. package/es/icon/ExportPDF.d.ts +3 -0
  18. package/es/icon/ExportPDF.d.ts.map +1 -0
  19. package/es/icon/ExportPDF.js +24 -0
  20. package/es/icon/TextCopy.d.ts +3 -0
  21. package/es/icon/TextCopy.d.ts.map +1 -0
  22. package/es/icon/TextCopy.js +25 -0
  23. package/es/icon/TextFileIcon.d.ts +3 -0
  24. package/es/icon/TextFileIcon.d.ts.map +1 -0
  25. package/es/icon/TextFileIcon.js +26 -0
  26. package/es/icon/TextIcon.d.ts +3 -0
  27. package/es/icon/TextIcon.d.ts.map +1 -0
  28. package/es/icon/TextIcon.js +28 -0
  29. package/es/index.d.ts.map +1 -0
  30. package/es/tools/UeditorResourceLoader.d.ts.map +1 -0
  31. package/es/tools/exportPDF.d.ts +27 -0
  32. package/es/tools/exportPDF.d.ts.map +1 -0
  33. package/es/tools/exportPDF.js +146 -0
  34. package/es/tools/filterHtmlNode.d.ts.map +1 -0
  35. package/es/tools/generateStylesFromSettings.d.ts +38 -0
  36. package/es/tools/generateStylesFromSettings.d.ts.map +1 -0
  37. package/es/tools/generateStylesFromSettings.js +24 -0
  38. package/es/tools/loadScript.d.ts.map +1 -0
  39. package/es/type.d.ts +21 -0
  40. package/es/type.d.ts.map +1 -0
  41. package/lib/LcdpUeditor.d.ts +10 -4
  42. package/lib/LcdpUeditor.js +62 -8
  43. package/lib/ToolBottomBar/FormatModal/index.d.ts +9 -0
  44. package/lib/ToolBottomBar/FormatModal/index.js +261 -0
  45. package/lib/ToolBottomBar/FormatModal/index.less +276 -0
  46. package/lib/ToolBottomBar/ProgressModal/index.d.ts +10 -0
  47. package/lib/ToolBottomBar/ProgressModal/index.js +73 -0
  48. package/lib/ToolBottomBar/ProgressModal/index.less +16 -0
  49. package/lib/ToolBottomBar/index.d.ts +33 -0
  50. package/lib/ToolBottomBar/index.js +235 -0
  51. package/lib/ToolBottomBar/index.less +75 -0
  52. package/lib/icon/ExportPDF.d.ts +3 -0
  53. package/lib/icon/ExportPDF.js +57 -0
  54. package/lib/icon/TextCopy.d.ts +3 -0
  55. package/lib/icon/TextCopy.js +39 -0
  56. package/lib/icon/TextFileIcon.d.ts +3 -0
  57. package/lib/icon/TextFileIcon.js +39 -0
  58. package/lib/icon/TextIcon.d.ts +3 -0
  59. package/lib/icon/TextIcon.js +39 -0
  60. package/lib/tools/exportPDF.d.ts +27 -0
  61. package/lib/tools/exportPDF.js +95 -0
  62. package/lib/tools/generateStylesFromSettings.d.ts +38 -0
  63. package/lib/tools/generateStylesFromSettings.js +77 -0
  64. package/lib/type.d.ts +21 -0
  65. package/package.json +8 -3
  66. package/ueditor-resource/dialogs/anchor/anchor.html +1 -1
  67. package/ueditor-resource/dialogs/attachment/attachment.html +3 -3
  68. package/ueditor-resource/dialogs/attachment/attachment.js +1 -1
  69. package/ueditor-resource/dialogs/audio/audio.js +1 -1
  70. package/ueditor-resource/dialogs/background/background.html +2 -2
  71. package/ueditor-resource/dialogs/background/background.js +1 -1
  72. package/ueditor-resource/dialogs/contentimport/contentimport.html +3 -3
  73. package/ueditor-resource/dialogs/contentimport/contentimport.js +1 -1
  74. package/ueditor-resource/dialogs/emotion/emotion.html +2 -2
  75. package/ueditor-resource/dialogs/emotion/emotion.js +1 -1
  76. package/ueditor-resource/dialogs/formula/formula.html +4 -4
  77. package/ueditor-resource/dialogs/formula/formula.js +1 -1
  78. package/ueditor-resource/dialogs/help/help.html +2 -2
  79. package/ueditor-resource/dialogs/help/help.js +1 -1
  80. package/ueditor-resource/dialogs/image/image.js +1 -1
  81. package/ueditor-resource/dialogs/insertframe/insertframe.html +1 -1
  82. package/ueditor-resource/dialogs/internal.js +1 -1
  83. package/ueditor-resource/dialogs/preview/preview.html +2 -2
  84. package/ueditor-resource/dialogs/scrawl/scrawl.html +2 -2
  85. package/ueditor-resource/dialogs/scrawl/scrawl.js +1 -1
  86. package/ueditor-resource/dialogs/searchreplace/searchreplace.html +2 -2
  87. package/ueditor-resource/dialogs/searchreplace/searchreplace.js +1 -1
  88. package/ueditor-resource/dialogs/spechars/spechars.html +2 -2
  89. package/ueditor-resource/dialogs/spechars/spechars.js +1 -1
  90. package/ueditor-resource/dialogs/table/edittable.html +2 -2
  91. package/ueditor-resource/dialogs/table/edittable.js +1 -1
  92. package/ueditor-resource/dialogs/table/edittd.html +1 -1
  93. package/ueditor-resource/dialogs/table/edittip.html +1 -1
  94. package/ueditor-resource/dialogs/template/template.html +2 -2
  95. package/ueditor-resource/dialogs/template/template.js +1 -1
  96. package/ueditor-resource/dialogs/video/video.js +1 -1
  97. package/ueditor-resource/dialogs/wordimage/wordimage.html +4 -4
  98. package/ueditor-resource/dialogs/wordimage/wordimage.js +1 -1
  99. package/ueditor-resource/plugins/browser-image-compression.js +9 -0
  100. package/ueditor-resource/plugins/demo/demo.js +3 -1
  101. package/ueditor-resource/themes/default/css/ueditor.css +1 -1
  102. package/ueditor-resource/third-party/SyntaxHighlighter/shCore.js +3 -3
  103. package/ueditor-resource/third-party/clipboard/clipboard.js +1 -1
  104. package/ueditor-resource/third-party/codemirror/codemirror.js +3 -2
  105. package/ueditor-resource/third-party/jquery-3.5.1.js +3 -3
  106. package/ueditor-resource/third-party/jquery-3.5.1_1.js +3 -3
  107. package/ueditor-resource/ueditor.all.js +22 -19
  108. package/ueditor-resource/ueditor.config.js +1 -1
  109. package/ueditor-resource/ueditor.parse.js +1 -1
@@ -33,11 +33,13 @@ __export(LcdpUeditor_exports, {
33
33
  });
34
34
  module.exports = __toCommonJS(LcdpUeditor_exports);
35
35
  var import_react = __toESM(require("react"));
36
+ var import_react_dom = __toESM(require("react-dom"));
36
37
  var import_const = require("./const");
37
38
  var import_defaultConfig = __toESM(require("./defaultConfig.json"));
38
39
  var import_UeditorResourceLoader = __toESM(require("./tools/UeditorResourceLoader"));
39
40
  var import_debounce = __toESM(require("lodash/debounce"));
40
41
  var import_filterHtmlNode = require("./tools/filterHtmlNode");
42
+ var import_ToolBottomBar = __toESM(require("./ToolBottomBar"));
41
43
  var LcdpUeditor = class extends import_react.default.Component {
42
44
  constructor(props) {
43
45
  super(props);
@@ -66,20 +68,24 @@ var LcdpUeditor = class extends import_react.default.Component {
66
68
  */
67
69
  this.currentContent = "";
68
70
  /**
69
- * 是否加载完成
71
+ * 是否全屏
70
72
  */
71
- this.isReady = false;
73
+ this.prefixCls = "pcfactory";
72
74
  /**
73
75
  * 初始加载失败
74
76
  */
75
77
  this.state = {
76
- initError: false
78
+ initError: false,
79
+ /**
80
+ * 是否加载完成
81
+ */
82
+ isReady: false
77
83
  };
78
84
  /**
79
85
  * 编辑器配置项
80
86
  */
81
87
  this.editorConfig = {};
82
- const { config } = props;
88
+ const { config, prefixCls, onFormatChange } = props;
83
89
  this.containerId = `ueditor_${Date.now()}_${String(Math.random()).slice(2, 6)}`;
84
90
  if (this.props.ueditorPath) {
85
91
  this.ueditorPath = this.props.ueditorPath;
@@ -103,6 +109,7 @@ var LcdpUeditor = class extends import_react.default.Component {
103
109
  }
104
110
  return null;
105
111
  };
112
+ this.prefixCls = prefixCls || "pcfactory";
106
113
  this.editorConfig = {
107
114
  ...import_defaultConfig.default,
108
115
  maximumWords: (config == null ? void 0 : config.maximumWords) || 1e4,
@@ -113,7 +120,9 @@ var LcdpUeditor = class extends import_react.default.Component {
113
120
  },
114
121
  uploadFunction: this.uploadFunction,
115
122
  initialContent: "",
116
- pasteplain: (config == null ? void 0 : config.pasteplain) === true
123
+ pasteplain: (config == null ? void 0 : config.pasteplain) === true,
124
+ onFormatChange,
125
+ exportFileName: (config == null ? void 0 : config.exportFileName) || "未命名"
117
126
  };
118
127
  this.debounceContentChange = (0, import_debounce.default)(this.onContentChange.bind(this), 300);
119
128
  }
@@ -121,7 +130,7 @@ var LcdpUeditor = class extends import_react.default.Component {
121
130
  this.initUeditor();
122
131
  }
123
132
  componentWillReceiveProps(nextProps) {
124
- if (this.isReady) {
133
+ if (this.state.isReady) {
125
134
  if ("value" in nextProps && this.currentContent !== nextProps.value) {
126
135
  this.isReportFlag = false;
127
136
  this.ueditorInst.setContent((0, import_filterHtmlNode.filterHtmlNode)(nextProps.value || "").str);
@@ -135,9 +144,15 @@ var LcdpUeditor = class extends import_react.default.Component {
135
144
  }
136
145
  }
137
146
  }
147
+ componentDidUpdate(prevProps) {
148
+ var _a, _b, _c;
149
+ if (this.state.isReady && (prevProps.defaultFormatSetting !== this.props.defaultFormatSetting || prevProps.bottomTypes !== this.props.bottomTypes || ((_a = prevProps == null ? void 0 : prevProps.config) == null ? void 0 : _a.exportFileName) !== ((_c = (_b = this.props) == null ? void 0 : _b.config) == null ? void 0 : _c.exportFileName))) {
150
+ this.renderStatusBar();
151
+ }
152
+ }
138
153
  componentWillUnmount() {
139
154
  var _a, _b, _c;
140
- if (this.isReady) {
155
+ if (this.state.isReady) {
141
156
  const editorBody = (_a = this.ueditorInst) == null ? void 0 : _a.body;
142
157
  if (editorBody && this.compositionEndHandler) {
143
158
  editorBody.removeEventListener("compositionend", this.compositionEndHandler);
@@ -259,7 +274,9 @@ var LcdpUeditor = class extends import_react.default.Component {
259
274
  if (nextValue) {
260
275
  this.ueditorInst.setContent(nextValue);
261
276
  }
262
- this.isReady = true;
277
+ this.setState({
278
+ isReady: true
279
+ });
263
280
  if (this.props.disabled) {
264
281
  this.ueditorInst.setDisabled();
265
282
  } else {
@@ -277,6 +294,7 @@ var LcdpUeditor = class extends import_react.default.Component {
277
294
  }
278
295
  this.initStyle();
279
296
  this.mountRef();
297
+ this.renderStatusBar();
280
298
  });
281
299
  };
282
300
  import_UeditorResourceLoader.default.onReady(readyFunc);
@@ -288,6 +306,42 @@ var LcdpUeditor = class extends import_react.default.Component {
288
306
  });
289
307
  import_UeditorResourceLoader.default.startLoad(jsList);
290
308
  }
309
+ /**
310
+ * 渲染状态栏
311
+ */
312
+ renderStatusBar() {
313
+ var _a, _b, _c, _d;
314
+ const { id } = this.ueditorInst.ui || {};
315
+ const bottomBarContainer = (_a = this.containerRef.current) == null ? void 0 : _a.querySelector(`#${id}_bottombar`);
316
+ const comp = /* @__PURE__ */ import_react.default.createElement(
317
+ import_ToolBottomBar.default,
318
+ {
319
+ ueditorInst: this.ueditorInst,
320
+ prefixCls: this.prefixCls,
321
+ containerRef: this.containerRef,
322
+ defaultFormatSetting: this.props.defaultFormatSetting,
323
+ onFormatChange: this.editorConfig.onFormatChange,
324
+ isReady: this.state.isReady,
325
+ bottomTypes: this.props.bottomTypes,
326
+ exportFileName: (_c = (_b = this.props) == null ? void 0 : _b.config) == null ? void 0 : _c.exportFileName
327
+ }
328
+ );
329
+ if (bottomBarContainer) {
330
+ let statusContainer = bottomBarContainer.querySelector(`#${id}_bottomStatusBar`);
331
+ bottomBarContainer.classList.remove("ueditor-bottom-bar-with-status");
332
+ if ((_d = this.props.bottomTypes) == null ? void 0 : _d.length) {
333
+ bottomBarContainer.classList.add("ueditor-bottom-bar-with-status");
334
+ if (!statusContainer) {
335
+ statusContainer = document.createElement("div");
336
+ statusContainer.id = `${id}_bottomStatusBar`;
337
+ bottomBarContainer.appendChild(statusContainer);
338
+ }
339
+ import_react_dom.default.render(comp, statusContainer);
340
+ } else if (statusContainer) {
341
+ statusContainer.remove();
342
+ }
343
+ }
344
+ }
291
345
  render() {
292
346
  const { initError } = this.state;
293
347
  if (initError) {
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import './index.less';
3
+ import { FormatSettings } from '../../tools/generateStylesFromSettings';
4
+ interface FormatSettingsPanelProps {
5
+ onApply: (settings: FormatSettings) => void;
6
+ initialSettings?: Partial<FormatSettings>;
7
+ }
8
+ declare const FormatSettingsPanel: React.FC<React.PropsWithChildren<FormatSettingsPanelProps>>;
9
+ export default FormatSettingsPanel;
@@ -0,0 +1,261 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/ToolBottomBar/FormatModal/index.tsx
30
+ var FormatModal_exports = {};
31
+ __export(FormatModal_exports, {
32
+ default: () => FormatModal_default
33
+ });
34
+ module.exports = __toCommonJS(FormatModal_exports);
35
+ var import_antd = require("antd");
36
+ var import_react = __toESM(require("react"));
37
+ var import_index = require("./index.less");
38
+ var suffixCls = "ueditor-format";
39
+ var SYSTEM_FONT_STACK = "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Helvetica, Arial, sans-serif";
40
+ var defaultSettings = {
41
+ headings: {
42
+ h1: { fontSize: "28px", fontFamily: "系统字体", fontWeight: "700", lineHeight: "1.3", color: "#1a202c", marginTop: "2.5rem", marginBottom: "1.2rem" },
43
+ h2: { fontSize: "24px", fontFamily: "系统字体", fontWeight: "600", lineHeight: "1.3", color: "#1a202c", marginTop: "2.5rem", marginBottom: "1.2rem" },
44
+ h3: { fontSize: "20px", fontFamily: "系统字体", fontWeight: "600", lineHeight: "1.3", color: "#1a202c", marginTop: "2rem", marginBottom: "0.8rem" },
45
+ h4: { fontSize: "18px", fontFamily: "系统字体", fontWeight: "600", lineHeight: "1.3", color: "#1a202c", marginTop: "2rem", marginBottom: "0.8rem" },
46
+ h5: { fontSize: "16px", fontFamily: "系统字体", fontWeight: "600", lineHeight: "1.3", color: "#1a202c", marginTop: "2rem", marginBottom: "0.8rem" },
47
+ h6: { fontSize: "16px", fontFamily: "系统字体", fontWeight: "600", lineHeight: "1.3", color: "#1a202c", marginTop: "2rem", marginBottom: "0.8rem" }
48
+ },
49
+ paragraph: { fontSize: "16px", fontFamily: "系统字体", fontWeight: "normal", lineHeight: "1.7", color: "#2c3e50" },
50
+ lists: {
51
+ ul: { fontSize: "16px", fontFamily: "系统字体", fontWeight: "normal", lineHeight: "1.7", color: "#2c3e50", paddingLeft: "1rem", marginTop: "1rem", marginBottom: "1rem" },
52
+ ol: { fontSize: "16px", fontFamily: "系统字体", fontWeight: "normal", lineHeight: "1.7", color: "#2c3e50", paddingLeft: "1rem", marginTop: "1rem", marginBottom: "1rem" }
53
+ }
54
+ };
55
+ var getOSType = () => {
56
+ const userAgent = navigator.userAgent.toLowerCase();
57
+ if (userAgent.includes("win"))
58
+ return "windows";
59
+ if (userAgent.includes("mac"))
60
+ return "mac";
61
+ if (userAgent.includes("linux"))
62
+ return "linux";
63
+ return "unknown";
64
+ };
65
+ var isFontAvailable = (fontName) => {
66
+ if (fontName === "系统字体" || fontName.includes(",") || fontName.includes("sans-serif") || fontName.includes("serif") || fontName.includes("monospace")) {
67
+ return true;
68
+ }
69
+ if ("fonts" in document) {
70
+ try {
71
+ return document.fonts.check(`12px "${fontName}"`);
72
+ } catch (e) {
73
+ }
74
+ }
75
+ try {
76
+ const canvas = document.createElement("canvas");
77
+ const context = canvas.getContext("2d");
78
+ if (!context)
79
+ return false;
80
+ const testText = "abcdefghijklmnopqrstuvwxyz测试字体ABCDEFG";
81
+ context.font = "72px monospace";
82
+ const baselineWidth = context.measureText(testText).width;
83
+ context.font = `72px "${fontName}", monospace`;
84
+ const testWidth = context.measureText(testText).width;
85
+ return Math.abs(testWidth - baselineWidth) > 2;
86
+ } catch (e) {
87
+ console.warn(`字体检测失败: ${fontName}`, e);
88
+ return false;
89
+ }
90
+ };
91
+ var generateFontOptions = () => {
92
+ const osType = getOSType();
93
+ const baseFonts = [
94
+ { value: "系统字体", label: "系统字体(推荐)" },
95
+ { value: "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Helvetica, Arial, sans-serif", label: "完整系统字体栈" }
96
+ ];
97
+ const platformFonts = {
98
+ windows: [
99
+ { value: "微软雅黑", label: "微软雅黑" },
100
+ { value: "仿宋", label: "仿宋" },
101
+ { value: "黑体", label: "黑体" },
102
+ { value: "楷体", label: "楷体" },
103
+ { value: "宋体", label: "宋体" },
104
+ { value: "等线", label: "等线" },
105
+ { value: "Segoe UI", label: "Segoe UI" },
106
+ { value: "Calibri", label: "Calibri" }
107
+ ],
108
+ mac: [
109
+ { value: "PingFang SC", label: "苹方(简)" },
110
+ { value: "PingFang TC", label: "苹方(繁)" },
111
+ { value: "Hiragino Sans GB", label: "冬青黑体" },
112
+ { value: "STHeiti", label: "华文黑体" },
113
+ { value: "STKaiti", label: "华文楷体" },
114
+ { value: "STSong", label: "华文宋体" },
115
+ { value: "STFangsong", label: "华文仿宋" },
116
+ { value: "San Francisco", label: "旧金山字体" },
117
+ { value: "Helvetica Neue", label: "Helvetica Neue" }
118
+ ],
119
+ linux: [
120
+ { value: "Noto Sans CJK SC", label: "思源黑体" },
121
+ { value: "Noto Serif CJK SC", label: "思源宋体" },
122
+ { value: "Source Han Sans", label: "Source Han Sans" },
123
+ { value: "WenQuanYi Micro Hei", label: "文泉驿微米黑" },
124
+ { value: "WenQuanYi Zen Hei", label: "文泉驿正黑" },
125
+ { value: "DejaVu Sans", label: "DejaVu Sans" },
126
+ { value: "Liberation Sans", label: "Liberation Sans" }
127
+ ]
128
+ };
129
+ const webSafeFonts = [
130
+ { value: "Arial", label: "Arial" },
131
+ { value: "Helvetica", label: "Helvetica" },
132
+ { value: "Times New Roman", label: "Times New Roman" },
133
+ { value: "Times", label: "Times" },
134
+ { value: "Courier New", label: "Courier New" },
135
+ { value: "Georgia", label: "Georgia" },
136
+ { value: "Verdana", label: "Verdana" },
137
+ { value: "sans-serif", label: "系统无衬线字体" },
138
+ { value: "serif", label: "系统衬线字体" },
139
+ { value: "monospace", label: "系统等宽字体" }
140
+ ];
141
+ const allFonts = [...baseFonts];
142
+ if (platformFonts[osType]) {
143
+ allFonts.push(...platformFonts[osType]);
144
+ }
145
+ allFonts.push(...webSafeFonts);
146
+ const availableFonts = allFonts.map((font) => ({
147
+ ...font,
148
+ available: isFontAvailable(font.value)
149
+ }));
150
+ return availableFonts.map((font) => ({
151
+ value: font.value,
152
+ label: font.available ? font.label : `${font.label} (不可用)`,
153
+ disabled: !font.available && !["系统字体", "完整系统字体栈"].includes(font.label)
154
+ }));
155
+ };
156
+ var fontFamilyOptions = generateFontOptions();
157
+ var fontWeightOptions = [
158
+ { value: "normal", label: "常规" },
159
+ { value: "500", label: "中等" },
160
+ { value: "600", label: "半粗" },
161
+ { value: "bold", label: "粗体" }
162
+ ];
163
+ var fontSizeOptions = [
164
+ { value: "12px", label: "12px" },
165
+ { value: "14px", label: "14px" },
166
+ { value: "16px", label: "16px" },
167
+ { value: "18px", label: "18px" },
168
+ { value: "20px", label: "20px" },
169
+ { value: "22px", label: "22px" },
170
+ { value: "24px", label: "24px" },
171
+ { value: "28px", label: "28px" },
172
+ { value: "32px", label: "32px" },
173
+ { value: "36px", label: "36px" },
174
+ { value: "1.0em", label: "1.0em" },
175
+ { value: "1.2em", label: "1.2em" },
176
+ { value: "1.5em", label: "1.5em" },
177
+ { value: "1.8em", label: "1.8em" }
178
+ ];
179
+ var FormatSettingsPanel = ({ onApply, initialSettings, children }) => {
180
+ const [form] = import_antd.Form.useForm();
181
+ const [open, setOpen] = (0, import_react.useState)(false);
182
+ const [settings, setSettings] = (0, import_react.useState)({
183
+ ...defaultSettings
184
+ });
185
+ const [currentOS, setCurrentOS] = (0, import_react.useState)("");
186
+ (0, import_react.useEffect)(() => {
187
+ if (initialSettings) {
188
+ const processFontFamily = (obj) => {
189
+ for (const key in obj) {
190
+ if (typeof obj[key] === "object" && obj[key] !== null) {
191
+ processFontFamily(obj[key]);
192
+ } else if (key === "fontFamily" && obj[key] === SYSTEM_FONT_STACK) {
193
+ obj[key] = "系统字体";
194
+ }
195
+ }
196
+ };
197
+ processFontFamily(initialSettings);
198
+ setSettings((pre) => ({
199
+ ...pre,
200
+ ...initialSettings
201
+ }));
202
+ }
203
+ }, [initialSettings]);
204
+ (0, import_react.useEffect)(() => {
205
+ const osType = getOSType();
206
+ const osNames = {
207
+ windows: "Windows",
208
+ mac: "macOS",
209
+ linux: "Linux",
210
+ unknown: "未知系统"
211
+ };
212
+ setCurrentOS(osNames[osType] || "未知系统");
213
+ }, []);
214
+ (0, import_react.useEffect)(() => {
215
+ if (open) {
216
+ form.setFieldsValue(settings);
217
+ }
218
+ }, [open, form, settings]);
219
+ const handleValuesChange = (changedValues, allValues) => {
220
+ setSettings((prev) => ({
221
+ ...prev,
222
+ ...allValues
223
+ }));
224
+ };
225
+ const handleApply = () => {
226
+ form.validateFields().then((values) => {
227
+ const processedValues = JSON.parse(JSON.stringify(values));
228
+ const processFontFamily = (obj) => {
229
+ for (const key in obj) {
230
+ if (typeof obj[key] === "object" && obj[key] !== null) {
231
+ processFontFamily(obj[key]);
232
+ } else if (key === "fontFamily" && obj[key] === "系统字体") {
233
+ obj[key] = SYSTEM_FONT_STACK;
234
+ }
235
+ }
236
+ };
237
+ processFontFamily(processedValues);
238
+ onApply(processedValues);
239
+ setOpen(false);
240
+ });
241
+ };
242
+ const handleCancel = () => {
243
+ setOpen(false);
244
+ };
245
+ const renderStyleRow = (prefix, label, style) => /* @__PURE__ */ import_react.default.createElement("div", { className: `${suffixCls}-style-row` }, /* @__PURE__ */ import_react.default.createElement("div", { className: `${suffixCls}-row-label` }, label), /* @__PURE__ */ import_react.default.createElement(import_antd.Row, { gutter: 12 }, /* @__PURE__ */ import_react.default.createElement(import_antd.Col, { span: 7 }, /* @__PURE__ */ import_react.default.createElement(import_antd.Form.Item, { name: [...prefix.split("."), "fontFamily"], noStyle: true }, /* @__PURE__ */ import_react.default.createElement(import_antd.Select, { placeholder: "字体", options: fontFamilyOptions, size: "small" }))), /* @__PURE__ */ import_react.default.createElement(import_antd.Col, { span: 5 }, /* @__PURE__ */ import_react.default.createElement(import_antd.Form.Item, { name: [...prefix.split("."), "fontSize"], noStyle: true }, /* @__PURE__ */ import_react.default.createElement(import_antd.Select, { placeholder: "字号", options: fontSizeOptions, size: "small" }))), /* @__PURE__ */ import_react.default.createElement(import_antd.Col, { span: 4 }, /* @__PURE__ */ import_react.default.createElement(import_antd.Form.Item, { name: [...prefix.split("."), "fontWeight"], noStyle: true }, /* @__PURE__ */ import_react.default.createElement(import_antd.Select, { placeholder: "字重", options: fontWeightOptions, size: "small" }))), /* @__PURE__ */ import_react.default.createElement(import_antd.Col, { span: 4 }, /* @__PURE__ */ import_react.default.createElement(import_antd.Form.Item, { name: [...prefix.split("."), "lineHeight"], noStyle: true }, /* @__PURE__ */ import_react.default.createElement(import_antd.InputNumber, { placeholder: "行高", step: 0.1, min: 1, max: 3, size: "small", style: { width: "100%" } }))), /* @__PURE__ */ import_react.default.createElement(import_antd.Col, { span: 4 }, /* @__PURE__ */ import_react.default.createElement(import_antd.Form.Item, { name: [...prefix.split("."), "color"], noStyle: true }, /* @__PURE__ */ import_react.default.createElement(import_antd.Input, { type: "color", style: { width: "100%", padding: 0, height: 24 } })))));
246
+ const content = /* @__PURE__ */ import_react.default.createElement("div", { className: `${suffixCls}-popover-content` }, /* @__PURE__ */ import_react.default.createElement("div", { className: `${suffixCls}-system-info` }, "当前系统: ", currentOS, " | 字体选项已针对您的系统优化"), /* @__PURE__ */ import_react.default.createElement(import_antd.Form, { form, layout: "vertical", initialValues: settings, onValuesChange: handleValuesChange, size: "small" }, /* @__PURE__ */ import_react.default.createElement("div", { className: `${suffixCls}-section` }, renderStyleRow("paragraph", "正文", settings.paragraph), renderStyleRow("headings.h1", "主标题", settings.headings.h1), renderStyleRow("headings.h2", "二级标题", settings.headings.h2), renderStyleRow("headings.h3", "三级标题", settings.headings.h3), renderStyleRow("headings.h4", "四级标题", settings.headings.h4), renderStyleRow("headings.h5", "五级标题", settings.headings.h5), renderStyleRow("headings.h6", "六级标题", settings.headings.h6), renderStyleRow("lists.ul", "无序列表", settings.lists.ul), renderStyleRow("lists.ol", "有序列表", settings.lists.ol)), /* @__PURE__ */ import_react.default.createElement("div", { className: `${suffixCls}-footer` }, /* @__PURE__ */ import_react.default.createElement(import_antd.Button, { size: "small", onClick: handleCancel }, "取消"), /* @__PURE__ */ import_react.default.createElement(import_antd.Button, { size: "small", type: "primary", onClick: handleApply }, "应用"))));
247
+ return /* @__PURE__ */ import_react.default.createElement(
248
+ import_antd.Popover,
249
+ {
250
+ content,
251
+ title: "格式设置",
252
+ trigger: "click",
253
+ visible: open,
254
+ onVisibleChange: setOpen,
255
+ placement: "bottomRight",
256
+ overlayClassName: `${suffixCls}-settings-popover`
257
+ },
258
+ children
259
+ );
260
+ };
261
+ var FormatModal_default = FormatSettingsPanel;
@@ -0,0 +1,276 @@
1
+ @prefixCls: pcfactory;
2
+ @suffixCls: ueditor-format;
3
+ .@{suffixCls}-settings-popover {
4
+ max-width: 720px;
5
+
6
+ input[type="color"] {
7
+ -webkit-appearance: none;
8
+ border: none;
9
+ padding: 0;
10
+ cursor: pointer;
11
+
12
+ &::-webkit-color-swatch-wrapper {
13
+ padding: 0;
14
+ border-radius: 2px;
15
+ }
16
+
17
+ &::-webkit-color-swatch {
18
+ border: none;
19
+ border-radius: 2px;
20
+ }
21
+ }
22
+
23
+ .@{prefixCls}-form-item {
24
+ margin-bottom: 0;
25
+ }
26
+
27
+ .@{prefixCls}-form-item-control-input {
28
+ min-height: 28px;
29
+ }
30
+
31
+ .@{suffixCls}-popover-content {
32
+ width: 680px;
33
+ padding: 0;
34
+ }
35
+
36
+ .@{prefixCls}-popover-inner-content {
37
+ padding: 16px 20px;
38
+ border-radius: 8px;
39
+ }
40
+
41
+ .@{prefixCls}-popover-title {
42
+ font-weight: 600;
43
+ text-align: center;
44
+ font-size: 16px;
45
+ color: #1a202c;
46
+ padding: 16px 20px 12px;
47
+ border-bottom: 1px solid #e2e8f0;
48
+ margin-bottom: 0;
49
+ }
50
+ }
51
+
52
+ .@{suffixCls}-section {
53
+ overflow-y: auto;
54
+ padding: 0;
55
+ max-height: 400px;
56
+ }
57
+
58
+ .@{suffixCls}-style-row {
59
+ margin-bottom: 8px;
60
+ padding: 12px 16px;
61
+ border-bottom: 1px solid #f0f0f0;
62
+ border-radius: 6px;
63
+ background-color: #fafbfc;
64
+ transition: all 0.2s ease;
65
+ display: flex;
66
+ align-items: center;
67
+
68
+ &:hover {
69
+ background-color: #f1f5f9;
70
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
71
+ }
72
+
73
+ &:last-child {
74
+ border-bottom: none;
75
+ margin-bottom: 0;
76
+ }
77
+
78
+ .@{suffixCls}-row-label {
79
+ font-weight: 600;
80
+ font-size: 14px;
81
+ width: 80px;
82
+ color: #374151;
83
+ flex-shrink: 0;
84
+ margin-right: 12px;
85
+ margin-bottom: 0;
86
+ }
87
+
88
+ .@{prefixCls}-row {
89
+ flex: 1;
90
+ align-items: center;
91
+ margin: 0;
92
+ .@{prefixCls}-select-selector {
93
+ width: 100%;
94
+ }
95
+ }
96
+
97
+ .@{prefixCls}-col {
98
+ margin-bottom: 0;
99
+ display: flex;
100
+ align-items: center;
101
+ }
102
+
103
+ .@{prefixCls}-select {
104
+ width: 100%;
105
+
106
+ .@{prefixCls}-select-selector {
107
+ border-radius: 4px;
108
+ border-color: #d1d5db;
109
+ transition: all 0.2s ease;
110
+ height: 28px;
111
+
112
+ .@{prefixCls}-select-selection-item {
113
+ line-height: 26px;
114
+ }
115
+
116
+ &:hover {
117
+ border-color: #6366f1;
118
+ }
119
+ }
120
+
121
+ &.@{prefixCls}-select-focused .@{prefixCls}-select-selector {
122
+ border-color: #6366f1 !important;
123
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.1) !important;
124
+ }
125
+ }
126
+
127
+ .@{prefixCls}-input-number {
128
+ width: 100%;
129
+ border-radius: 4px;
130
+ border-color: #d1d5db;
131
+ height: 28px;
132
+
133
+ .@{prefixCls}-input-number-input {
134
+ height: 26px;
135
+ }
136
+
137
+ &:hover {
138
+ border-color: #6366f1;
139
+ }
140
+
141
+ &:focus,
142
+ &.@{prefixCls}-input-number-focused {
143
+ border-color: #6366f1 !important;
144
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.1) !important;
145
+ }
146
+ }
147
+
148
+ input[type="color"] {
149
+ width: 100%;
150
+ height: 28px;
151
+ border-radius: 4px;
152
+ border: 1px solid #d1d5db;
153
+ cursor: pointer;
154
+
155
+ &:hover {
156
+ border-color: #6366f1;
157
+ }
158
+ }
159
+ }
160
+
161
+ .@{suffixCls}-footer {
162
+ display: flex;
163
+ justify-content: flex-end;
164
+ gap: 12px;
165
+ margin-top: 16px;
166
+ padding-top: 12px;
167
+ border-top: 1px solid #e2e8f0;
168
+
169
+ .@{prefixCls}-btn {
170
+ height: 32px;
171
+ padding: 0 16px;
172
+ border-radius: 4px;
173
+ font-weight: 500;
174
+ transition: all 0.2s ease;
175
+
176
+ &.@{prefixCls}-btn-default {
177
+ border-color: #d1d5db;
178
+ color: #6b7280;
179
+
180
+ &:hover {
181
+ border-color: #9ca3af;
182
+ color: #374151;
183
+ }
184
+ }
185
+
186
+ &.@{prefixCls}-btn-primary {
187
+ background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
188
+ border: none;
189
+ box-shadow: 0 2px 4px rgba(99, 102, 241, 0.2);
190
+
191
+ &:hover {
192
+ background: linear-gradient(135deg, #5b61f0 0%, #7c3aed 100%);
193
+ box-shadow: 0 4px 8px rgba(99, 102, 241, 0.3);
194
+ transform: translateY(-1px);
195
+ }
196
+ }
197
+ }
198
+ }
199
+
200
+ @media (max-width: 768px) {
201
+ .@{suffixCls}-settings-popover {
202
+ max-width: 95vw;
203
+
204
+ .@{suffixCls}-popover-content {
205
+ width: calc(95vw - 40px);
206
+ }
207
+ }
208
+
209
+ .@{suffixCls}-style-row {
210
+ flex-direction: column;
211
+ align-items: stretch;
212
+
213
+ .@{suffixCls}-row-label {
214
+ width: 100%;
215
+ margin-right: 0;
216
+ margin-bottom: 8px;
217
+ }
218
+
219
+ .@{prefixCls}-row {
220
+ width: 100%;
221
+ }
222
+
223
+ .@{prefixCls}-col {
224
+ margin-bottom: 8px;
225
+
226
+ &:last-child {
227
+ margin-bottom: 0;
228
+ }
229
+ }
230
+ }
231
+ }
232
+
233
+ .@{suffixCls}-style-section {
234
+ margin-bottom: 15px;
235
+ }
236
+
237
+ .@{suffixCls}-section-title {
238
+ font-weight: 500;
239
+ margin-bottom: 10px;
240
+ font-size: 15px;
241
+ }
242
+
243
+ .@{suffixCls}-system-info {
244
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
245
+ color: white !important;
246
+ border-radius: 8px !important;
247
+ padding: 12px 16px !important;
248
+ margin-bottom: 16px !important;
249
+ text-align: center !important;
250
+ font-size: 13px !important;
251
+ font-weight: 500 !important;
252
+ box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2) !important;
253
+ }
254
+
255
+ .@{suffixCls}-section::-webkit-scrollbar {
256
+ width: 6px;
257
+ }
258
+
259
+ .@{suffixCls}-section::-webkit-scrollbar-track {
260
+ background: #f1f5f9;
261
+ border-radius: 3px;
262
+ }
263
+
264
+ .@{suffixCls}-section::-webkit-scrollbar-thumb {
265
+ background: #cbd5e1;
266
+ border-radius: 3px;
267
+
268
+ &:hover {
269
+ background: #94a3b8;
270
+ }
271
+ }
272
+
273
+ .@{suffixCls}-section.loading {
274
+ opacity: 0.6;
275
+ pointer-events: none;
276
+ }