@ctzhian/tiptap 2.12.9 → 2.13.0

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.
@@ -5,6 +5,7 @@ interface AttachmentContentProps {
5
5
  type: 'icon' | 'block';
6
6
  isPdf: boolean;
7
7
  editable?: boolean;
8
+ updateAttributes?: (attrs: Partial<AttachmentAttributes>) => void;
8
9
  }
9
10
  /**
10
11
  * 附件内容组件
@@ -16,8 +16,8 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
16
16
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
17
17
  import { Download2LineIcon, FileIcon } from "../../../component/Icons";
18
18
  import { EyeLineIcon } from "../../../component/Icons/eye-line-icon";
19
- import { Box, IconButton, Stack } from "@mui/material";
20
- import React, { useState } from "react";
19
+ import { alpha, Box, IconButton, Stack, useTheme } from "@mui/material";
20
+ import React, { useCallback, useEffect, useRef, useState } from "react";
21
21
  /**
22
22
  * 附件内容组件
23
23
  * 用于渲染附件的实际内容,支持编辑和只读模式
@@ -27,11 +27,23 @@ export var AttachmentContent = function AttachmentContent(_ref) {
27
27
  type = _ref.type,
28
28
  isPdf = _ref.isPdf,
29
29
  _ref$editable = _ref.editable,
30
- editable = _ref$editable === void 0 ? false : _ref$editable;
30
+ editable = _ref$editable === void 0 ? false : _ref$editable,
31
+ updateAttributes = _ref.updateAttributes;
32
+ var theme = useTheme();
31
33
  var _useState = useState(false),
32
34
  _useState2 = _slicedToArray(_useState, 2),
33
35
  isHovered = _useState2[0],
34
36
  setIsHovered = _useState2[1];
37
+ var _useState3 = useState(false),
38
+ _useState4 = _slicedToArray(_useState3, 2),
39
+ isDragging = _useState4[0],
40
+ setIsDragging = _useState4[1];
41
+ var _useState5 = useState(null),
42
+ _useState6 = _slicedToArray(_useState5, 2),
43
+ dragCorner = _useState6[0],
44
+ setDragCorner = _useState6[1];
45
+ var dragStartYRef = useRef(0);
46
+ var dragStartHeightRef = useRef(0);
35
47
  var handlePreview = function handlePreview(e) {
36
48
  e.preventDefault();
37
49
  e.stopPropagation();
@@ -92,6 +104,52 @@ export var AttachmentContent = function AttachmentContent(_ref) {
92
104
  return _ref2.apply(this, arguments);
93
105
  };
94
106
  }();
107
+
108
+ // 拖拽调整高度
109
+ var handleMouseDown = function handleMouseDown(e, corner) {
110
+ e.preventDefault();
111
+ e.stopPropagation();
112
+ setIsDragging(true);
113
+ setDragCorner(corner);
114
+ dragStartYRef.current = e.clientY;
115
+ dragStartHeightRef.current = attrs.height || 300;
116
+ };
117
+ var handleMouseMove = useCallback(function (e) {
118
+ if (!isDragging || !dragCorner) return;
119
+ var deltaY = e.clientY - dragStartYRef.current;
120
+ var newHeight;
121
+
122
+ // 根据不同的角计算高度变化
123
+ if (dragCorner === 'bottom-left' || dragCorner === 'bottom-right') {
124
+ // 下角:向下拉伸,高度增加
125
+ newHeight = dragStartHeightRef.current + deltaY;
126
+ } else {
127
+ // 上角:向上拉伸,高度增加(deltaY 为负时高度增加)
128
+ newHeight = dragStartHeightRef.current - deltaY;
129
+ }
130
+
131
+ // 限制高度范围:最小 200px,最大 1000px
132
+ newHeight = Math.max(200, Math.min(1000, newHeight));
133
+ if (updateAttributes) {
134
+ updateAttributes({
135
+ height: newHeight
136
+ });
137
+ }
138
+ }, [isDragging, dragCorner, updateAttributes]);
139
+ var handleMouseUp = useCallback(function () {
140
+ setIsDragging(false);
141
+ setDragCorner(null);
142
+ }, []);
143
+ useEffect(function () {
144
+ if (isDragging) {
145
+ document.addEventListener('mousemove', handleMouseMove);
146
+ document.addEventListener('mouseup', handleMouseUp);
147
+ return function () {
148
+ document.removeEventListener('mousemove', handleMouseMove);
149
+ document.removeEventListener('mouseup', handleMouseUp);
150
+ };
151
+ }
152
+ }, [isDragging, handleMouseMove, handleMouseUp]);
95
153
  var blockStyles = editable ? {
96
154
  display: 'flex',
97
155
  border: '1px solid',
@@ -149,32 +207,117 @@ export var AttachmentContent = function AttachmentContent(_ref) {
149
207
  color: 'primary.main',
150
208
  cursor: 'pointer'
151
209
  };
152
- return /*#__PURE__*/React.createElement(React.Fragment, null, type === 'block' ? attrs.view === '1' && isPdf && attrs.url && attrs.url !== 'error' ? /*#__PURE__*/React.createElement(Box, _extends({
153
- sx: _objectSpread(_objectSpread({}, blockStyles), {}, {
154
- p: 0,
155
- overflow: 'hidden'
156
- })
157
- }, !editable && {
158
- 'data-title': attrs.title,
159
- 'data-type': type
160
- }, {
210
+ return /*#__PURE__*/React.createElement(React.Fragment, null, type === 'block' ? attrs.view === '1' && isPdf && attrs.url && attrs.url !== 'error' ? /*#__PURE__*/React.createElement(Box, {
211
+ sx: {
212
+ position: 'relative'
213
+ },
161
214
  onMouseEnter: function onMouseEnter() {
162
215
  return setIsHovered(true);
163
216
  },
164
217
  onMouseLeave: function onMouseLeave() {
165
218
  return setIsHovered(false);
166
219
  }
220
+ }, /*#__PURE__*/React.createElement(Box, _extends({
221
+ sx: _objectSpread(_objectSpread({}, blockStyles), {}, {
222
+ p: 0,
223
+ overflow: 'hidden',
224
+ height: "".concat(attrs.height || 300, "px")
225
+ })
226
+ }, !editable && {
227
+ 'data-title': attrs.title,
228
+ 'data-type': type
167
229
  }), /*#__PURE__*/React.createElement("iframe", {
168
230
  src: attrs.url + '#navpanes=0&toolbar=1',
169
231
  width: "100%",
170
- height: "300px",
232
+ height: "100%",
171
233
  allowFullScreen: true,
172
234
  style: {
173
235
  border: 'none',
174
- display: 'block'
236
+ display: 'block',
237
+ pointerEvents: isDragging ? 'none' : 'auto'
175
238
  },
176
239
  title: attrs.title
177
- })) : /*#__PURE__*/React.createElement(Box, _extends({}, !editable && {
240
+ })), editable && (isHovered || isDragging) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Box, {
241
+ onMouseDown: function onMouseDown(e) {
242
+ return handleMouseDown(e, 'top-left');
243
+ },
244
+ sx: {
245
+ position: 'absolute',
246
+ left: -4,
247
+ top: -4,
248
+ width: 12,
249
+ height: 12,
250
+ bgcolor: 'background.default',
251
+ cursor: 'ns-resize',
252
+ borderRadius: '50%',
253
+ border: '2px solid',
254
+ borderColor: isDragging && dragCorner === 'top-left' ? 'primary.main' : alpha(theme.palette.primary.main, 0.3),
255
+ '&:hover': {
256
+ borderColor: 'primary.main'
257
+ },
258
+ transition: 'background-color 0.2s ease'
259
+ }
260
+ }), /*#__PURE__*/React.createElement(Box, {
261
+ onMouseDown: function onMouseDown(e) {
262
+ return handleMouseDown(e, 'top-right');
263
+ },
264
+ sx: {
265
+ position: 'absolute',
266
+ right: -4,
267
+ top: -4,
268
+ width: 12,
269
+ height: 12,
270
+ bgcolor: 'background.default',
271
+ cursor: 'ns-resize',
272
+ borderRadius: '50%',
273
+ border: '2px solid',
274
+ borderColor: isDragging && dragCorner === 'top-right' ? 'primary.main' : alpha(theme.palette.primary.main, 0.3),
275
+ '&:hover': {
276
+ borderColor: 'primary.main'
277
+ },
278
+ transition: 'background-color 0.2s ease'
279
+ }
280
+ }), /*#__PURE__*/React.createElement(Box, {
281
+ onMouseDown: function onMouseDown(e) {
282
+ return handleMouseDown(e, 'bottom-left');
283
+ },
284
+ sx: {
285
+ position: 'absolute',
286
+ left: -4,
287
+ bottom: -2,
288
+ width: 12,
289
+ height: 12,
290
+ cursor: 'ns-resize',
291
+ borderRadius: '50%',
292
+ border: '2px solid',
293
+ bgcolor: 'background.default',
294
+ borderColor: isDragging && dragCorner === 'bottom-left' ? 'primary.main' : alpha(theme.palette.primary.main, 0.3),
295
+ '&:hover': {
296
+ borderColor: 'primary.main'
297
+ },
298
+ transition: 'background-color 0.2s ease'
299
+ }
300
+ }), /*#__PURE__*/React.createElement(Box, {
301
+ onMouseDown: function onMouseDown(e) {
302
+ return handleMouseDown(e, 'bottom-right');
303
+ },
304
+ sx: {
305
+ position: 'absolute',
306
+ right: -4,
307
+ bottom: -2,
308
+ width: 12,
309
+ height: 12,
310
+ bgcolor: 'background.default',
311
+ cursor: 'ns-resize',
312
+ borderRadius: '50%',
313
+ border: '2px solid',
314
+ borderColor: isDragging && dragCorner === 'bottom-right' ? 'primary.main' : alpha(theme.palette.primary.main, 0.3),
315
+ '&:hover': {
316
+ borderColor: 'primary.main'
317
+ },
318
+ transition: 'background-color 0.2s ease'
319
+ }
320
+ }))) : /*#__PURE__*/React.createElement(Box, _extends({}, !editable && {
178
321
  'data-title': attrs.title,
179
322
  'data-type': attrs.type
180
323
  }, {
@@ -7,6 +7,7 @@ export interface AttachmentAttributes {
7
7
  type: string;
8
8
  size: string;
9
9
  view?: string;
10
+ height?: number;
10
11
  }
11
12
  declare const AttachmentViewWrapper: React.FC<NodeViewProps & EditorFnProps & {
12
13
  attachmentType?: 'icon' | 'block';
@@ -258,7 +258,8 @@ var AttachmentViewWrapper = function AttachmentViewWrapper(_ref) {
258
258
  isPdf: isPdf,
259
259
  attrs: attrs,
260
260
  type: attachmentDisplayType === 'block' ? 'block' : 'icon',
261
- editable: true
261
+ editable: true,
262
+ updateAttributes: updateAttributes
262
263
  }))), /*#__PURE__*/React.createElement(FloatingPopover, {
263
264
  open: Boolean(anchorEl),
264
265
  anchorEl: anchorEl,
@@ -21,6 +21,7 @@ declare module '@tiptap/core' {
21
21
  title: string;
22
22
  size: string;
23
23
  view?: '0' | '1';
24
+ height?: number;
24
25
  }) => ReturnType;
25
26
  };
26
27
  }
@@ -175,6 +175,18 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
175
175
  };
176
176
  }
177
177
  },
178
+ height: {
179
+ default: 300,
180
+ parseHTML: function parseHTML(element) {
181
+ var height = element.getAttribute('data-height');
182
+ return height ? parseInt(height, 10) : 300;
183
+ },
184
+ renderHTML: function renderHTML(attributes) {
185
+ return {
186
+ 'data-height': attributes.height || 300
187
+ };
188
+ }
189
+ },
178
190
  url: {
179
191
  default: '',
180
192
  parseHTML: function parseHTML(element) {
@@ -228,8 +240,10 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
228
240
  getAttrs: function getAttrs(dom) {
229
241
  if (!(dom instanceof HTMLElement)) return false;
230
242
  var viewAttr = dom.getAttribute('data-view');
243
+ var heightAttr = dom.getAttribute('data-height');
231
244
  return {
232
245
  view: viewAttr !== null ? viewAttr : '0',
246
+ height: heightAttr ? parseInt(heightAttr, 10) : 300,
233
247
  url: dom.getAttribute('data-url') || '',
234
248
  title: dom.getAttribute('data-title') || '',
235
249
  size: dom.getAttribute('data-size') || '0',
@@ -243,6 +257,7 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
243
257
  var download = dom.getAttribute('download');
244
258
  var type = dom.getAttribute('type');
245
259
  var view = dom.getAttribute('data-view') || '0';
260
+ var heightAttr = dom.getAttribute('data-height');
246
261
 
247
262
  // 只解析 type="block" 的带 download 的 <a> 标签
248
263
  if (download === null || type !== 'block') {
@@ -252,6 +267,7 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
252
267
  var title = dom.textContent || dom.getAttribute('title') || dom.getAttribute('download') || '';
253
268
  return {
254
269
  view: view,
270
+ height: heightAttr ? parseInt(heightAttr, 10) : 300,
255
271
  url: href,
256
272
  title: title,
257
273
  size: '0',
@@ -270,9 +286,10 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
270
286
  var _ref5 = node.attrs,
271
287
  url = _ref5.url,
272
288
  title = _ref5.title,
273
- view = _ref5.view;
289
+ view = _ref5.view,
290
+ height = _ref5.height;
274
291
  if (!url) return '';
275
- return "<a href=\"".concat(url, "\" data-view=\"").concat(view, "\" type=\"block\" target=\"_blank\" download=\"").concat(title, "\">").concat(title, "</a>");
292
+ return "<a href=\"".concat(url, "\" data-view=\"").concat(view, "\" data-height=\"").concat(height || 300, "\" type=\"block\" target=\"_blank\" download=\"").concat(title, "\">").concat(title, "</a>");
276
293
  },
277
294
  addCommands: function addCommands() {
278
295
  var _this3 = this;
@@ -284,6 +301,7 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
284
301
  type: _this3.name,
285
302
  attrs: {
286
303
  view: options.view || '0',
304
+ height: options.height || 300,
287
305
  url: options.url || '',
288
306
  title: options.title || '',
289
307
  size: options.size || '0',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctzhian/tiptap",
3
- "version": "2.12.9",
3
+ "version": "2.13.0",
4
4
  "description": "基于 Tiptap 二次开发的编辑器组件",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",