@lowdefy/blocks-tiptap 5.6.0 → 6.0.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.
- package/dist/blocks/TiptapInput/TiptapInput.js +27 -7
- package/dist/blocks/TiptapInput/gallery.yaml +210 -0
- package/dist/blocks/TiptapInput/meta.js +10 -2
- package/dist/blocks/TiptapInput/style.css +60 -0
- package/dist/blocks/TiptapInput/tests/TiptapInput.e2e.yaml +53 -0
- package/dist/blocks/TiptapInput/tests.yaml +65 -0
- package/dist/blocks/TiptapInput/useTiptapState.js +6 -5
- package/dist/blocks/TiptapMentionInput/TiptapMentionInput.js +26 -6
- package/dist/blocks/TiptapMentionInput/gallery.yaml +296 -0
- package/dist/blocks/TiptapMentionInput/meta.js +10 -2
- package/dist/blocks/TiptapMentionInput/{style.module.css → style.css} +39 -39
- package/dist/blocks/TiptapMentionInput/tests/TiptapMentionInput.e2e.yaml +140 -0
- package/dist/blocks/TiptapMentionInput/tests.yaml +90 -0
- package/dist/blocks/TiptapMentionInput/useTiptapMentionState.js +5 -4
- package/dist/blocks/utils/fileUpload.js +63 -0
- package/dist/blocks/utils/statusClass.js +1 -1
- package/dist/blocks/utils/{style.module.css → style.css} +56 -50
- package/package.json +11 -10
- package/dist/blocks/TiptapInput/style.module.css +0 -60
- package/dist/blocks/utils/s3FileUpload.js +0 -53
|
@@ -22,14 +22,17 @@ import buildExtensions from '../utils/buildExtensions.js';
|
|
|
22
22
|
import computeHeightStyle from '../utils/computeHeightStyle.js';
|
|
23
23
|
import statusClass from '../utils/statusClass.js';
|
|
24
24
|
import useTiptapState from './useTiptapState.js';
|
|
25
|
-
import './style.
|
|
25
|
+
import './style.css';
|
|
26
26
|
const TiptapInput = ({ blockId, components: { Icon, Link }, events, loading, methods, properties, required, validation, value })=>{
|
|
27
|
+
const uploadPolicyRequestId = properties.uploadPolicyRequestId ?? properties.s3PostPolicyRequestId;
|
|
28
|
+
const downloadPolicyRequestId = properties.downloadPolicyRequestId;
|
|
27
29
|
const { emit, insertImage } = useTiptapState({
|
|
28
30
|
value,
|
|
29
|
-
methods
|
|
31
|
+
methods,
|
|
32
|
+
hasDownloadRequest: !type.isNone(downloadPolicyRequestId)
|
|
30
33
|
});
|
|
31
34
|
const disabled = properties.disabled === true || loading;
|
|
32
|
-
const uploadEnabled = !type.isNone(
|
|
35
|
+
const uploadEnabled = !type.isNone(uploadPolicyRequestId);
|
|
33
36
|
const extensions = buildExtensions({
|
|
34
37
|
properties,
|
|
35
38
|
insertImage,
|
|
@@ -51,21 +54,38 @@ const TiptapInput = ({ blockId, components: { Icon, Link }, events, loading, met
|
|
|
51
54
|
});
|
|
52
55
|
}
|
|
53
56
|
});
|
|
54
|
-
// Register upload-policy
|
|
57
|
+
// Register upload-policy and download-policy events once (if configured).
|
|
55
58
|
useEffect(()=>{
|
|
56
59
|
if (!uploadEnabled) return;
|
|
60
|
+
if (!type.isNone(properties.s3PostPolicyRequestId)) {
|
|
61
|
+
console.warn('TiptapInput property "s3PostPolicyRequestId" is deprecated. Use "uploadPolicyRequestId" instead.');
|
|
62
|
+
}
|
|
57
63
|
methods.registerEvent({
|
|
58
|
-
name: '
|
|
64
|
+
name: '__getUploadPolicy',
|
|
59
65
|
actions: [
|
|
60
66
|
{
|
|
61
|
-
id: '
|
|
67
|
+
id: '__getUploadPolicy',
|
|
62
68
|
type: 'Request',
|
|
63
69
|
params: [
|
|
64
|
-
|
|
70
|
+
uploadPolicyRequestId
|
|
65
71
|
]
|
|
66
72
|
}
|
|
67
73
|
]
|
|
68
74
|
});
|
|
75
|
+
if (!type.isNone(downloadPolicyRequestId)) {
|
|
76
|
+
methods.registerEvent({
|
|
77
|
+
name: '__getDownloadPolicy',
|
|
78
|
+
actions: [
|
|
79
|
+
{
|
|
80
|
+
id: '__getDownloadPolicy',
|
|
81
|
+
type: 'Request',
|
|
82
|
+
params: [
|
|
83
|
+
downloadPolicyRequestId
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
});
|
|
88
|
+
}
|
|
69
89
|
}, []);
|
|
70
90
|
// Register methods as soon as the editor is available.
|
|
71
91
|
useEffect(()=>{
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Copyright 2020-2026 Lowdefy, Inc
|
|
2
|
+
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
- title: Default
|
|
16
|
+
fullWidth: true
|
|
17
|
+
blocks:
|
|
18
|
+
- id: tiptap_default
|
|
19
|
+
type: TiptapInput
|
|
20
|
+
properties:
|
|
21
|
+
title: Notes
|
|
22
|
+
placeholder: 'Start typing here. Try **bold**, *italic*, or headings.'
|
|
23
|
+
|
|
24
|
+
- title: Pre-populated content
|
|
25
|
+
fullWidth: true
|
|
26
|
+
blocks:
|
|
27
|
+
- id: tiptap_prepopulated
|
|
28
|
+
type: TiptapInput
|
|
29
|
+
events:
|
|
30
|
+
onMount:
|
|
31
|
+
- id: tiptap_prepopulated_set
|
|
32
|
+
type: SetState
|
|
33
|
+
params:
|
|
34
|
+
tiptap_prepopulated:
|
|
35
|
+
html: >
|
|
36
|
+
<h2>What's new</h2>
|
|
37
|
+
<p>Highlights from this release:</p>
|
|
38
|
+
<ul>
|
|
39
|
+
<li>Rich-text editor built on <a href="https://tiptap.dev">TipTap</a></li>
|
|
40
|
+
<li>Drag-and-drop image uploads</li>
|
|
41
|
+
<li>Inline <strong>bold</strong>, <em>italic</em>, and <mark>highlights</mark></li>
|
|
42
|
+
</ul>
|
|
43
|
+
<blockquote><p>Pair it with a TextArea when you need a simple fallback.</p></blockquote>
|
|
44
|
+
properties:
|
|
45
|
+
title: Release notes
|
|
46
|
+
|
|
47
|
+
- title: Disabled (read-only)
|
|
48
|
+
fullWidth: true
|
|
49
|
+
blocks:
|
|
50
|
+
- id: tiptap_disabled
|
|
51
|
+
type: TiptapInput
|
|
52
|
+
events:
|
|
53
|
+
onMount:
|
|
54
|
+
- id: tiptap_disabled_set
|
|
55
|
+
type: SetState
|
|
56
|
+
params:
|
|
57
|
+
tiptap_disabled:
|
|
58
|
+
html: '<p>This editor is disabled and cannot be edited.</p>'
|
|
59
|
+
properties:
|
|
60
|
+
title: Read only
|
|
61
|
+
disabled: true
|
|
62
|
+
|
|
63
|
+
- title: Borderless
|
|
64
|
+
fullWidth: true
|
|
65
|
+
blocks:
|
|
66
|
+
- id: tiptap_borderless
|
|
67
|
+
type: TiptapInput
|
|
68
|
+
properties:
|
|
69
|
+
title: Borderless editor
|
|
70
|
+
bordered: false
|
|
71
|
+
placeholder: 'No border, just content.'
|
|
72
|
+
|
|
73
|
+
- title: Fixed rows — rows = 2
|
|
74
|
+
fullWidth: true
|
|
75
|
+
blocks:
|
|
76
|
+
- id: tiptap_rows_2
|
|
77
|
+
type: TiptapInput
|
|
78
|
+
properties:
|
|
79
|
+
title: Short note
|
|
80
|
+
placeholder: 'Exactly 2 rows tall.'
|
|
81
|
+
rows: 2
|
|
82
|
+
|
|
83
|
+
- title: autoSize — minRows 2, maxRows 5
|
|
84
|
+
fullWidth: true
|
|
85
|
+
blocks:
|
|
86
|
+
- id: tiptap_autosize_range
|
|
87
|
+
type: TiptapInput
|
|
88
|
+
properties:
|
|
89
|
+
title: Grows between 2 and 5 rows
|
|
90
|
+
placeholder: 'Keep typing — scrolls past 5 rows.'
|
|
91
|
+
autoSize:
|
|
92
|
+
minRows: 2
|
|
93
|
+
maxRows: 5
|
|
94
|
+
|
|
95
|
+
- title: Validation — required, with error state
|
|
96
|
+
fullWidth: true
|
|
97
|
+
blocks:
|
|
98
|
+
- id: tiptap_validation
|
|
99
|
+
type: TiptapInput
|
|
100
|
+
required: true
|
|
101
|
+
properties:
|
|
102
|
+
title: Release notes (required)
|
|
103
|
+
placeholder: 'Type at least 10 characters, then click Validate.'
|
|
104
|
+
rows: 3
|
|
105
|
+
validate:
|
|
106
|
+
- status: error
|
|
107
|
+
message: 'Release notes must be at least 10 characters.'
|
|
108
|
+
pass:
|
|
109
|
+
_gte:
|
|
110
|
+
- _string.length:
|
|
111
|
+
_state: tiptap_validation.text
|
|
112
|
+
- 10
|
|
113
|
+
- id: tiptap_validation_button
|
|
114
|
+
type: Button
|
|
115
|
+
properties:
|
|
116
|
+
title: Validate
|
|
117
|
+
events:
|
|
118
|
+
onClick:
|
|
119
|
+
- id: tiptap_validation_run
|
|
120
|
+
type: Validate
|
|
121
|
+
params:
|
|
122
|
+
- tiptap_validation
|
|
123
|
+
|
|
124
|
+
- title: autoSize = true — grows with content
|
|
125
|
+
fullWidth: true
|
|
126
|
+
blocks:
|
|
127
|
+
- id: tiptap_autosize_true
|
|
128
|
+
type: TiptapInput
|
|
129
|
+
properties:
|
|
130
|
+
title: Unconstrained
|
|
131
|
+
placeholder: 'No height cap.'
|
|
132
|
+
autoSize: true
|
|
133
|
+
|
|
134
|
+
- title: Minimal — tables, images and highlights disabled
|
|
135
|
+
fullWidth: true
|
|
136
|
+
blocks:
|
|
137
|
+
- id: tiptap_minimal
|
|
138
|
+
type: TiptapInput
|
|
139
|
+
properties:
|
|
140
|
+
title: Plain note
|
|
141
|
+
placeholder: 'Bold/italic/lists only.'
|
|
142
|
+
image:
|
|
143
|
+
disabled: true
|
|
144
|
+
table:
|
|
145
|
+
disabled: true
|
|
146
|
+
highlight:
|
|
147
|
+
disabled: true
|
|
148
|
+
|
|
149
|
+
- title: StarterKit overrides — disable code block and blockquote
|
|
150
|
+
fullWidth: true
|
|
151
|
+
blocks:
|
|
152
|
+
- id: tiptap_starterkit
|
|
153
|
+
type: TiptapInput
|
|
154
|
+
properties:
|
|
155
|
+
title: Short-form
|
|
156
|
+
placeholder: 'No code block or blockquote.'
|
|
157
|
+
starterKit:
|
|
158
|
+
codeBlock: false
|
|
159
|
+
blockquote: false
|
|
160
|
+
horizontalRule: false
|
|
161
|
+
|
|
162
|
+
- title: With table (tables enabled by default)
|
|
163
|
+
fullWidth: true
|
|
164
|
+
blocks:
|
|
165
|
+
- id: tiptap_with_table
|
|
166
|
+
type: TiptapInput
|
|
167
|
+
events:
|
|
168
|
+
onMount:
|
|
169
|
+
- id: tiptap_with_table_set
|
|
170
|
+
type: SetState
|
|
171
|
+
params:
|
|
172
|
+
tiptap_with_table:
|
|
173
|
+
html: >
|
|
174
|
+
<h3>Weekly sync</h3>
|
|
175
|
+
<p>Schedule for today's meeting:</p>
|
|
176
|
+
<table>
|
|
177
|
+
<thead>
|
|
178
|
+
<tr><th>Time</th><th>Topic</th><th>Owner</th></tr>
|
|
179
|
+
</thead>
|
|
180
|
+
<tbody>
|
|
181
|
+
<tr><td>09:00</td><td>Kickoff</td><td>Alice</td></tr>
|
|
182
|
+
<tr><td>09:15</td><td>Review last week</td><td>Bob</td></tr>
|
|
183
|
+
<tr><td>09:45</td><td>This week's plan</td><td>Carol</td></tr>
|
|
184
|
+
<tr><td>10:00</td><td>Wrap-up</td><td>Alice</td></tr>
|
|
185
|
+
</tbody>
|
|
186
|
+
</table>
|
|
187
|
+
<p>Notes:</p>
|
|
188
|
+
<ul>
|
|
189
|
+
<li>Bring the latest metrics</li>
|
|
190
|
+
<li>Send follow-ups within 24h</li>
|
|
191
|
+
</ul>
|
|
192
|
+
properties:
|
|
193
|
+
title: Agenda
|
|
194
|
+
|
|
195
|
+
- title: Link configuration — open in place (not new tab)
|
|
196
|
+
fullWidth: true
|
|
197
|
+
blocks:
|
|
198
|
+
- id: tiptap_links
|
|
199
|
+
type: TiptapInput
|
|
200
|
+
events:
|
|
201
|
+
onMount:
|
|
202
|
+
- id: tiptap_links_set
|
|
203
|
+
type: SetState
|
|
204
|
+
params:
|
|
205
|
+
tiptap_links:
|
|
206
|
+
html: '<p>Visit <a href="https://lowdefy.com">lowdefy.com</a> or type a URL and press space.</p>'
|
|
207
|
+
properties:
|
|
208
|
+
title: Open links in place
|
|
209
|
+
link:
|
|
210
|
+
openOnClick: false
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
items: {
|
|
35
35
|
type: 'string'
|
|
36
36
|
},
|
|
37
|
-
description: 'Mime-types accepted by the drag/drop and paste file handler. Defaults to common image types (jpeg, png, gif, webp). Only used when
|
|
37
|
+
description: 'Mime-types accepted by the drag/drop and paste file handler. Defaults to common image types (jpeg, png, gif, webp). Only used when uploadPolicyRequestId is set.'
|
|
38
38
|
},
|
|
39
39
|
autoSize: {
|
|
40
40
|
oneOf: [
|
|
@@ -166,9 +166,17 @@
|
|
|
166
166
|
minimum: 1,
|
|
167
167
|
description: 'Fix the editor height to exactly this many rows. Takes precedence over autoSize.'
|
|
168
168
|
},
|
|
169
|
+
downloadPolicyRequestId: {
|
|
170
|
+
type: 'string',
|
|
171
|
+
description: 'Id of a download request (e.g. AwsS3PresignedGetObject) used to resolve the inserted image URL after upload. Inline images persist in saved content, so the request should set public: true (and the upload request the provider public-read acl) to return a stable, non-expiring URL. When unset, a legacy unsigned object URL is constructed from the upload response (S3-shaped, deprecated).'
|
|
172
|
+
},
|
|
169
173
|
s3PostPolicyRequestId: {
|
|
170
174
|
type: 'string',
|
|
171
|
-
description: '
|
|
175
|
+
description: 'Deprecated — use uploadPolicyRequestId instead.'
|
|
176
|
+
},
|
|
177
|
+
uploadPolicyRequestId: {
|
|
178
|
+
type: 'string',
|
|
179
|
+
description: 'Id of an upload-policy request (e.g. AwsS3PresignedPostPolicy, GcsSignedPostPolicy, AzureBlobUploadSas). When set, images dragged or pasted into the editor are uploaded via that request and inserted as <img> nodes. Leave unset to disable image uploads.'
|
|
172
180
|
},
|
|
173
181
|
size: {
|
|
174
182
|
type: 'string',
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
@import '../utils/style.css';
|
|
2
|
+
|
|
3
|
+
.tableWrapper,
|
|
4
|
+
.tiptap-table {
|
|
5
|
+
display: block;
|
|
6
|
+
overflow-x: auto;
|
|
7
|
+
max-width: 80%;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.tableWrapper table,
|
|
11
|
+
.tiptap-table table {
|
|
12
|
+
border-collapse: collapse;
|
|
13
|
+
width: 100%;
|
|
14
|
+
min-width: 75px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.tableWrapper colgroup col,
|
|
18
|
+
.tiptap-table colgroup col {
|
|
19
|
+
width: auto;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.tableWrapper table,
|
|
23
|
+
.tableWrapper th,
|
|
24
|
+
.tableWrapper td,
|
|
25
|
+
.tiptap-table table,
|
|
26
|
+
.tiptap-table th,
|
|
27
|
+
.tiptap-table td {
|
|
28
|
+
border: 1px solid var(--ant-color-border);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.tableWrapper th,
|
|
32
|
+
.tableWrapper td,
|
|
33
|
+
.tiptap-table th,
|
|
34
|
+
.tiptap-table td {
|
|
35
|
+
padding: 2px;
|
|
36
|
+
text-align: left;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.tableWrapper th,
|
|
40
|
+
.tiptap-table th {
|
|
41
|
+
background-color: var(--ant-color-fill-tertiary);
|
|
42
|
+
font-weight: bold;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.tableWrapper tr:nth-child(even),
|
|
46
|
+
.tiptap-table tr:nth-child(even) {
|
|
47
|
+
background-color: var(--ant-color-fill-quaternary);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.tableWrapper tr:hover,
|
|
51
|
+
.tiptap-table tr:hover {
|
|
52
|
+
background-color: var(--ant-color-primary-bg);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.tableWrapper td p,
|
|
56
|
+
.tableWrapper th p,
|
|
57
|
+
.tiptap-table td p,
|
|
58
|
+
.tiptap-table th p {
|
|
59
|
+
margin: 0;
|
|
60
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Copyright 2020-2026 Lowdefy, Inc
|
|
2
|
+
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
id: tiptap-input
|
|
16
|
+
type: Box
|
|
17
|
+
|
|
18
|
+
events:
|
|
19
|
+
onMount:
|
|
20
|
+
- id: seed_content
|
|
21
|
+
type: SetState
|
|
22
|
+
params:
|
|
23
|
+
tiptap_with_value:
|
|
24
|
+
html: '<p>Hello <strong>world</strong>.</p>'
|
|
25
|
+
tiptap_disabled:
|
|
26
|
+
html: '<p>Disabled content.</p>'
|
|
27
|
+
tiptap_borderless:
|
|
28
|
+
html: '<p>Borderless.</p>'
|
|
29
|
+
|
|
30
|
+
blocks:
|
|
31
|
+
- id: tiptap_empty
|
|
32
|
+
type: TiptapInput
|
|
33
|
+
|
|
34
|
+
- id: tiptap_placeholder
|
|
35
|
+
type: TiptapInput
|
|
36
|
+
properties:
|
|
37
|
+
placeholder: 'Start typing...'
|
|
38
|
+
|
|
39
|
+
- id: tiptap_with_value
|
|
40
|
+
type: TiptapInput
|
|
41
|
+
|
|
42
|
+
- id: tiptap_disabled
|
|
43
|
+
type: TiptapInput
|
|
44
|
+
properties:
|
|
45
|
+
disabled: true
|
|
46
|
+
|
|
47
|
+
- id: tiptap_borderless
|
|
48
|
+
type: TiptapInput
|
|
49
|
+
properties:
|
|
50
|
+
bordered: false
|
|
51
|
+
|
|
52
|
+
- id: tiptap_typing
|
|
53
|
+
type: TiptapInput
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright 2020-2026 Lowdefy, Inc
|
|
2
|
+
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
- id: default
|
|
16
|
+
type: TiptapInput
|
|
17
|
+
- id: properties.placeholder
|
|
18
|
+
type: TiptapInput
|
|
19
|
+
properties:
|
|
20
|
+
placeholder: 'Start typing...'
|
|
21
|
+
- id: properties.title
|
|
22
|
+
type: TiptapInput
|
|
23
|
+
properties:
|
|
24
|
+
title: 'Note'
|
|
25
|
+
- id: properties.disabled
|
|
26
|
+
type: TiptapInput
|
|
27
|
+
properties:
|
|
28
|
+
disabled: true
|
|
29
|
+
- id: properties.bordered = false
|
|
30
|
+
type: TiptapInput
|
|
31
|
+
properties:
|
|
32
|
+
bordered: false
|
|
33
|
+
placeholder: 'No border.'
|
|
34
|
+
- id: properties.image and table disabled
|
|
35
|
+
type: TiptapInput
|
|
36
|
+
properties:
|
|
37
|
+
image:
|
|
38
|
+
disabled: true
|
|
39
|
+
table:
|
|
40
|
+
disabled: true
|
|
41
|
+
- id: properties.starterKit overrides
|
|
42
|
+
type: TiptapInput
|
|
43
|
+
properties:
|
|
44
|
+
starterKit:
|
|
45
|
+
codeBlock: false
|
|
46
|
+
blockquote: false
|
|
47
|
+
- id: properties.rows = 2
|
|
48
|
+
type: TiptapInput
|
|
49
|
+
properties:
|
|
50
|
+
rows: 2
|
|
51
|
+
- id: properties.autoSize = {minRows 2, maxRows 5}
|
|
52
|
+
type: TiptapInput
|
|
53
|
+
properties:
|
|
54
|
+
autoSize:
|
|
55
|
+
minRows: 2
|
|
56
|
+
maxRows: 5
|
|
57
|
+
- id: properties.autoSize = true
|
|
58
|
+
type: TiptapInput
|
|
59
|
+
properties:
|
|
60
|
+
autoSize: true
|
|
61
|
+
- id: properties.link.openOnClick = false
|
|
62
|
+
type: TiptapInput
|
|
63
|
+
properties:
|
|
64
|
+
link:
|
|
65
|
+
openOnClick: false
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ import { useRef } from 'react';
|
|
16
16
|
import TurndownService from 'turndown';
|
|
17
|
-
import
|
|
17
|
+
import fileUpload from '../utils/fileUpload.js';
|
|
18
18
|
// Ref-tracked controller for the editor's value. No useState — the only
|
|
19
19
|
// source of truth for `fileList` is the `value` prop from Lowdefy. We mirror
|
|
20
20
|
// it into a ref each render so callbacks (onUpdate, insertImage) captured in
|
|
21
21
|
// closures always read the current value instead of a stale render snapshot.
|
|
22
|
-
function useTiptapState({ value, methods }) {
|
|
22
|
+
function useTiptapState({ value, methods, hasDownloadRequest }) {
|
|
23
23
|
const valueRef = useRef(value);
|
|
24
24
|
valueRef.current = value;
|
|
25
25
|
const turndownService = new TurndownService();
|
|
@@ -31,7 +31,7 @@ function useTiptapState({ value, methods }) {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
// Emit a full `{fileList, html, text, markdown}` value to Lowdefy based on
|
|
34
|
-
// the editor's current document. When appendFile is supplied (an
|
|
34
|
+
// the editor's current document. When appendFile is supplied (an upload
|
|
35
35
|
// result), it is added to the current fileList before filtering by
|
|
36
36
|
// in-document image urls.
|
|
37
37
|
const emit = (editor, appendFile)=>{
|
|
@@ -54,9 +54,10 @@ function useTiptapState({ value, methods }) {
|
|
|
54
54
|
});
|
|
55
55
|
};
|
|
56
56
|
const insertImage = async (editor, file, pos)=>{
|
|
57
|
-
const url = await
|
|
57
|
+
const url = await fileUpload({
|
|
58
58
|
file,
|
|
59
|
-
methods
|
|
59
|
+
methods,
|
|
60
|
+
hasDownloadRequest
|
|
60
61
|
});
|
|
61
62
|
// The upload is async: bail if the editor was torn down meanwhile (e.g. the
|
|
62
63
|
// surrounding page navigated away before the upload resolved), otherwise the
|
|
@@ -26,7 +26,7 @@ import statusClass from '../utils/statusClass.js';
|
|
|
26
26
|
import suggestion from './suggestion.js';
|
|
27
27
|
import useGroupMembersPopover from './useGroupMembersPopover.js';
|
|
28
28
|
import useTiptapMentionState from './useTiptapMentionState.js';
|
|
29
|
-
import './style.
|
|
29
|
+
import './style.css';
|
|
30
30
|
// A mention node's `id` attribute holds whatever option the user picked — a
|
|
31
31
|
// plain string, or the option object ({ label, value, tag }) — so the label
|
|
32
32
|
// and the DOM identifier are both derived from it. Content loaded back from
|
|
@@ -92,12 +92,15 @@ const LowdefyMention = Mention.extend({
|
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
94
|
const TiptapMentionInput = ({ blockId, components: { Icon, Link }, events, loading, methods, properties, required, validation, value })=>{
|
|
95
|
+
const uploadPolicyRequestId = properties.uploadPolicyRequestId ?? properties.s3PostPolicyRequestId;
|
|
96
|
+
const downloadPolicyRequestId = properties.downloadPolicyRequestId;
|
|
95
97
|
const { emit, insertImage } = useTiptapMentionState({
|
|
96
98
|
value,
|
|
97
|
-
methods
|
|
99
|
+
methods,
|
|
100
|
+
hasDownloadRequest: !type.isNone(downloadPolicyRequestId)
|
|
98
101
|
});
|
|
99
102
|
const disabled = properties.disabled === true || loading;
|
|
100
|
-
const uploadEnabled = !type.isNone(
|
|
103
|
+
const uploadEnabled = !type.isNone(uploadPolicyRequestId);
|
|
101
104
|
const char = properties.mentions?.char ?? '@';
|
|
102
105
|
const allowSpaces = properties.mentions?.allowSpaces !== false;
|
|
103
106
|
const limit = properties.mentions?.limit ?? 5;
|
|
@@ -186,18 +189,35 @@ const TiptapMentionInput = ({ blockId, components: { Icon, Link }, events, loadi
|
|
|
186
189
|
]);
|
|
187
190
|
useEffect(()=>{
|
|
188
191
|
if (uploadEnabled) {
|
|
192
|
+
if (!type.isNone(properties.s3PostPolicyRequestId)) {
|
|
193
|
+
console.warn('TiptapMentionInput property "s3PostPolicyRequestId" is deprecated. Use "uploadPolicyRequestId" instead.');
|
|
194
|
+
}
|
|
189
195
|
methods.registerEvent({
|
|
190
|
-
name: '
|
|
196
|
+
name: '__getUploadPolicy',
|
|
191
197
|
actions: [
|
|
192
198
|
{
|
|
193
|
-
id: '
|
|
199
|
+
id: '__getUploadPolicy',
|
|
194
200
|
type: 'Request',
|
|
195
201
|
params: [
|
|
196
|
-
|
|
202
|
+
uploadPolicyRequestId
|
|
197
203
|
]
|
|
198
204
|
}
|
|
199
205
|
]
|
|
200
206
|
});
|
|
207
|
+
if (!type.isNone(downloadPolicyRequestId)) {
|
|
208
|
+
methods.registerEvent({
|
|
209
|
+
name: '__getDownloadPolicy',
|
|
210
|
+
actions: [
|
|
211
|
+
{
|
|
212
|
+
id: '__getDownloadPolicy',
|
|
213
|
+
type: 'Request',
|
|
214
|
+
params: [
|
|
215
|
+
downloadPolicyRequestId
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
]
|
|
219
|
+
});
|
|
220
|
+
}
|
|
201
221
|
}
|
|
202
222
|
if (!type.isNone(properties.mentionsRequestId)) {
|
|
203
223
|
methods.registerEvent({
|