@modusoperandi/licit 0.14.3 → 0.14.14
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/TableCellMenuPlugin.js +8 -1
- package/dist/TableCellMenuPlugin.js.flow +7 -0
- package/dist/TableResizePlugin.js +3 -1
- package/dist/TableResizePlugin.js.flow +4 -3
- package/dist/bom.xml +735 -403
- package/dist/ui/TableCellMenu.js +12 -2
- package/dist/ui/TableCellMenu.js.flow +16 -3
- package/dist/ui/isElementFullyVisible.js +3 -1
- package/dist/ui/isElementFullyVisible.js.flow +4 -1
- package/licit/client/CustomLicitRuntime.js +219 -100
- package/licit/client/index.js +2 -2
- package/package.json +4 -6
- package/src/TableCellMenuPlugin.js +7 -0
- package/src/TableResizePlugin.js +4 -3
- package/src/ui/TableCellMenu.js +16 -3
- package/src/ui/isElementFullyVisible.js +4 -1
- package/webpack.config.js +3 -13
package/dist/ui/TableCellMenu.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _prosemirrorState = require("prosemirror-state");
|
|
8
8
|
var _prosemirrorView = require("prosemirror-view");
|
|
9
|
+
var _prosemirrorModel = require("prosemirror-model");
|
|
9
10
|
var React = _interopRequireWildcard(require("react"));
|
|
10
11
|
var _CommandMenuButton = _interopRequireDefault(require("./CommandMenuButton"));
|
|
11
12
|
var _EditorToolbarConfig = require("./EditorToolbarConfig");
|
|
@@ -26,11 +27,20 @@ class TableCellMenu extends React.PureComponent {
|
|
|
26
27
|
render() {
|
|
27
28
|
const {
|
|
28
29
|
editorState,
|
|
29
|
-
editorView
|
|
30
|
+
editorView,
|
|
31
|
+
pluginView,
|
|
32
|
+
actionNode
|
|
30
33
|
} = this.props;
|
|
34
|
+
let cmdGrps = null;
|
|
35
|
+
if (pluginView.getMenu) {
|
|
36
|
+
cmdGrps = pluginView.getMenu(editorState, actionNode, _EditorToolbarConfig.TABLE_COMMANDS_GROUP);
|
|
37
|
+
}
|
|
38
|
+
if (!cmdGrps) {
|
|
39
|
+
cmdGrps = _EditorToolbarConfig.TABLE_COMMANDS_GROUP;
|
|
40
|
+
}
|
|
31
41
|
return /*#__PURE__*/React.createElement(_CommandMenuButton.default, {
|
|
32
42
|
className: "czi-table-cell-menu",
|
|
33
|
-
commandGroups:
|
|
43
|
+
commandGroups: cmdGrps,
|
|
34
44
|
dispatch: editorView.dispatch,
|
|
35
45
|
editorState: editorState,
|
|
36
46
|
editorView: editorView,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @flow
|
|
2
|
-
import { EditorState } from 'prosemirror-state';
|
|
2
|
+
import { EditorState, PluginView } from 'prosemirror-state';
|
|
3
3
|
import { EditorView } from 'prosemirror-view';
|
|
4
|
+
import { Node } from 'prosemirror-model';
|
|
4
5
|
import * as React from 'react';
|
|
5
6
|
|
|
6
7
|
import CommandMenuButton from './CommandMenuButton';
|
|
@@ -12,6 +13,8 @@ import './czi-table-cell-menu.css';
|
|
|
12
13
|
type Props = {
|
|
13
14
|
editorState: EditorState,
|
|
14
15
|
editorView: EditorView,
|
|
16
|
+
pluginView: PluginView,
|
|
17
|
+
actionNode: Node,
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
class TableCellMenu extends React.PureComponent<any, any> {
|
|
@@ -20,11 +23,21 @@ class TableCellMenu extends React.PureComponent<any, any> {
|
|
|
20
23
|
props: Props;
|
|
21
24
|
|
|
22
25
|
render(): React.Element<any> {
|
|
23
|
-
const { editorState, editorView } = this.props;
|
|
26
|
+
const { editorState, editorView, pluginView, actionNode } = this.props;
|
|
27
|
+
let cmdGrps = null;
|
|
28
|
+
|
|
29
|
+
if (pluginView.getMenu) {
|
|
30
|
+
cmdGrps = pluginView.getMenu(editorState, actionNode, TABLE_COMMANDS_GROUP);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!cmdGrps) {
|
|
34
|
+
cmdGrps = TABLE_COMMANDS_GROUP;
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
return (
|
|
25
38
|
<CommandMenuButton
|
|
26
39
|
className="czi-table-cell-menu"
|
|
27
|
-
commandGroups={
|
|
40
|
+
commandGroups={cmdGrps}
|
|
28
41
|
dispatch={editorView.dispatch}
|
|
29
42
|
editorState={editorState}
|
|
30
43
|
editorView={editorView}
|
|
@@ -12,8 +12,10 @@ function isElementFullyVisible(el) {
|
|
|
12
12
|
w,
|
|
13
13
|
h
|
|
14
14
|
} = (0, _licitUiCommands.fromHTMlElement)(el);
|
|
15
|
+
// to handle the rounded border scenario.
|
|
16
|
+
const factor = '10px' === el.style.borderRadius ? 3 : 1;
|
|
15
17
|
// Only checks the top-left point.
|
|
16
|
-
const nwEl = w && h ? el.ownerDocument.elementFromPoint(x +
|
|
18
|
+
const nwEl = w && h ? el.ownerDocument.elementFromPoint(x + factor, y + factor) : null;
|
|
17
19
|
if (!nwEl) {
|
|
18
20
|
return false;
|
|
19
21
|
}
|
|
@@ -4,8 +4,11 @@ import { fromHTMlElement } from '@modusoperandi/licit-ui-commands';
|
|
|
4
4
|
|
|
5
5
|
export default function isElementFullyVisible(el: HTMLElement): boolean {
|
|
6
6
|
const { x, y, w, h } = fromHTMlElement(el);
|
|
7
|
+
// to handle the rounded border scenario.
|
|
8
|
+
const factor = '10px' === el.style.borderRadius ? 3 : 1;
|
|
7
9
|
// Only checks the top-left point.
|
|
8
|
-
const nwEl =
|
|
10
|
+
const nwEl =
|
|
11
|
+
w && h ? el.ownerDocument.elementFromPoint(x + factor, y + factor) : null;
|
|
9
12
|
|
|
10
13
|
if (!nwEl) {
|
|
11
14
|
return false;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// This implements the interface of `EditorRuntime`.
|
|
4
4
|
// To run editor directly:
|
|
5
5
|
import type { ImageLike } from '../../src/Types';
|
|
6
|
-
import { POST
|
|
6
|
+
import { POST } from '../../src/client/http';
|
|
7
7
|
|
|
8
8
|
// When use it in a componet:
|
|
9
9
|
|
|
@@ -12,42 +12,201 @@ import { POST, req } from '../../src/client/http';
|
|
|
12
12
|
import {POST } from '@modusoperandi/licit';
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
// const GLOSSARY_URI = 'http://greathints.com:3003';
|
|
16
|
+
|
|
17
|
+
type Glossary = {
|
|
18
|
+
id: string,
|
|
19
|
+
term: string,
|
|
20
|
+
description: string,
|
|
21
|
+
};
|
|
22
|
+
|
|
15
23
|
class CustomLicitRuntime {
|
|
24
|
+
getAcronyms(abbreviation: string): Promise<Glossary[]> {
|
|
25
|
+
return new Promise((resolve, _reject) => {
|
|
26
|
+
resolve([
|
|
27
|
+
{
|
|
28
|
+
id: '1',
|
|
29
|
+
term: 'ASAP',
|
|
30
|
+
description:
|
|
31
|
+
'ASAP is an acronym for as soon as possible. This common phrase means you will do something when you have the chance.',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: '2',
|
|
35
|
+
term: 'IMAX',
|
|
36
|
+
description:
|
|
37
|
+
'The IMAX in IMAX Theater actually stands for Image Maximum. This is a large-format movie theater.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: '3',
|
|
41
|
+
term: 'PIN',
|
|
42
|
+
description:
|
|
43
|
+
'When in all-caps, the word PIN stands for �personal identification number.� This is a secret number you create to access private documents, files and account information.',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: '4',
|
|
47
|
+
term: 'RADAR',
|
|
48
|
+
description:
|
|
49
|
+
'RADAR stands for �radio detection and ranging.� This technology is rarely called anything other than its acronym.',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: '5',
|
|
53
|
+
term: 'TASER',
|
|
54
|
+
description:
|
|
55
|
+
'The electrical weapon actually is an acronym for �Thomas A. Swift�s Electric Rifle.�',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: '6',
|
|
59
|
+
term: 'SCUBA',
|
|
60
|
+
description:
|
|
61
|
+
'This piece of diving equipment is an acronym for �self-contained underwater breathing apparatus.�',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: '7',
|
|
65
|
+
term: 'NASA',
|
|
66
|
+
description:
|
|
67
|
+
'NASA stands for �National Aeronautics and Space Administration,� and this organization once took a man to the moon.',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: '8',
|
|
71
|
+
term: 'NAFTA',
|
|
72
|
+
description:
|
|
73
|
+
'NAFTA is the acronym or the �North American Free Trade Agreement.� This organization governs trade among North American countries.',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: '9',
|
|
77
|
+
term: 'HIPAA',
|
|
78
|
+
description:
|
|
79
|
+
'The �Health Insurance Portability Accountability Act� is responsible for keeping medical information private.',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: '10',
|
|
83
|
+
term: 'DARE',
|
|
84
|
+
description:
|
|
85
|
+
'Most people no longer remember that DARE stands for �Drug Abuse Resistance Education�',
|
|
86
|
+
},
|
|
87
|
+
{ id: 11, term: 'AEF', description: 'air expeditionary force' },
|
|
88
|
+
{ id: 12, term: 'AFDP', description: 'Air Force Doctrine Publication' },
|
|
89
|
+
{
|
|
90
|
+
id: 13,
|
|
91
|
+
term: 'AvFID',
|
|
92
|
+
description: 'aviation foreign internal defense',
|
|
93
|
+
},
|
|
94
|
+
{ id: 14, term: 'BSZ', description: 'base security zone' },
|
|
95
|
+
{ id: 15, term: 'CS', description: 'combat support' },
|
|
96
|
+
{
|
|
97
|
+
id: 16,
|
|
98
|
+
term: 'COMAFFOR',
|
|
99
|
+
description: 'commander, Air Force forces',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 17,
|
|
103
|
+
term: 'COMAFSOF',
|
|
104
|
+
description: 'commander, Air Force special operations forces',
|
|
105
|
+
},
|
|
106
|
+
{ id: 18, term: 'CoL', description: 'continuum of learning' },
|
|
107
|
+
{
|
|
108
|
+
id: 19,
|
|
109
|
+
term: 'CTO',
|
|
110
|
+
description: 'counterthreat operations; cyber tasking order',
|
|
111
|
+
},
|
|
112
|
+
{ id: 20, term: 'DFC', description: 'defense force commander' },
|
|
113
|
+
{ id: 21, term: 'DCS', description: 'defensive counterspace' },
|
|
114
|
+
{
|
|
115
|
+
id: 22,
|
|
116
|
+
term: 'DIRSPACEFOR',
|
|
117
|
+
description: 'director of space forces',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 23,
|
|
121
|
+
term: 'EBAO',
|
|
122
|
+
description: 'effects-based approach to operations',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: 24,
|
|
126
|
+
term: 'EWIR',
|
|
127
|
+
description: 'electronic warfare integrated reprogramming',
|
|
128
|
+
},
|
|
129
|
+
{ id: 25, term: 'FPI', description: 'force protection intelligence' },
|
|
130
|
+
{
|
|
131
|
+
id: 26,
|
|
132
|
+
term: 'GAMSS',
|
|
133
|
+
description: 'Global Air Mobility Support System',
|
|
134
|
+
},
|
|
135
|
+
{ id: 27, term: 'JPPA', description: 'joint planning process for air' },
|
|
136
|
+
{ id: 28, term: 'OA', description: 'operational-level assessment' },
|
|
137
|
+
{ id: 29, term: 'OCS', description: 'offensive counterspace' },
|
|
138
|
+
{ id: 30, term: 'OWS', description: 'operational weather squadron' },
|
|
139
|
+
]);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
getGlossary(term: string): Promise<Glossary[]> {
|
|
144
|
+
return new Promise((resolve, _reject) => {
|
|
145
|
+
resolve([
|
|
146
|
+
{ id: '1', term: 'IAS', description: 'Indian Administrative Service' },
|
|
147
|
+
{ id: '2', term: 'IIT', description: 'Indian Institute of Technology' },
|
|
148
|
+
{ id: '3', term: 'CAS', description: 'Close Air Support' },
|
|
149
|
+
{ id: '4', term: 'CAS', description: 'Continuous Aerial Surveillance' },
|
|
150
|
+
{
|
|
151
|
+
id: '5',
|
|
152
|
+
term: 'Analysis of Variance (ANOVA)',
|
|
153
|
+
description:
|
|
154
|
+
'A statistical tool used to analyze the differences among means.',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: '6',
|
|
158
|
+
term: 'Confidence Interval (CI)',
|
|
159
|
+
description:
|
|
160
|
+
'The mean of an estimate 4/- the variation in the estimate.',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: '7',
|
|
164
|
+
term: 'Comma Separated Value (CSV)',
|
|
165
|
+
description:
|
|
166
|
+
'A text file that uses a comma (,) to separate each value inputted.',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: '8',
|
|
170
|
+
term: 'Mean Squared Error (MSE)',
|
|
171
|
+
description:
|
|
172
|
+
'A measurement of how close a fitted line is to plotted data points.',
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: '9',
|
|
176
|
+
term: 'Odds Ratio (OR)',
|
|
177
|
+
description:
|
|
178
|
+
'A quantification of the strength of association between two events.',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: '10',
|
|
182
|
+
term: 'Process Behavior Analysis (PBA)',
|
|
183
|
+
description: 'Written analysis of a Process Behavior Chart (PBC.)',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
id: '11',
|
|
187
|
+
term: 'Quality Assurance (QA)',
|
|
188
|
+
description:
|
|
189
|
+
'Systematic monitoring and evaluation to ensure standards are met.',
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: '12',
|
|
193
|
+
term: 'Root Mean Square (RMC)',
|
|
194
|
+
description:
|
|
195
|
+
'The square root of the mean square, or the quadratic mean.',
|
|
196
|
+
},
|
|
197
|
+
]);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
16
201
|
// Image Proxy
|
|
17
202
|
canProxyImageSrc(): boolean {
|
|
18
203
|
return false;
|
|
19
204
|
}
|
|
20
205
|
|
|
21
|
-
getProxyImageSrc(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const endPoint = 'https://moviacloud.modusoperandi.com/movia/content';
|
|
26
|
-
|
|
27
|
-
(async () => {
|
|
28
|
-
// image that will be fetched and appended
|
|
29
|
-
const imageURL = endPoint + id;
|
|
30
|
-
|
|
31
|
-
// Fetch remote URL, getting contents as binary blob
|
|
32
|
-
const vidBlob = await (
|
|
33
|
-
await fetch(imageURL, { headers: { Authorization: token } })
|
|
34
|
-
).blob();
|
|
35
|
-
|
|
36
|
-
const reader = new window.FileReader();
|
|
37
|
-
reader.addEventListener('error', () =>
|
|
38
|
-
reject(new Error('Failed to load image'))
|
|
39
|
-
);
|
|
40
|
-
reader.addEventListener('load', () =>
|
|
41
|
-
// Convert to ImageLike. Width and Height are unknown, and would
|
|
42
|
-
// require rendering into a hidden canvas to determine
|
|
43
|
-
resolve({
|
|
44
|
-
alt: vidBlob.name,
|
|
45
|
-
src: reader.result
|
|
46
|
-
})
|
|
47
|
-
);
|
|
48
|
-
reader.readAsDataURL(vidBlob);
|
|
49
|
-
})();
|
|
50
|
-
});
|
|
206
|
+
getProxyImageSrc(src: string): string {
|
|
207
|
+
// This simulate a fake proxy.
|
|
208
|
+
const suffix = 'proxied=1';
|
|
209
|
+
return src.indexOf('?') === -1 ? `${src}?${suffix}` : `${src}&${suffix}`;
|
|
51
210
|
}
|
|
52
211
|
|
|
53
212
|
// Image Upload
|
|
@@ -94,33 +253,8 @@ class CustomLicitRuntime {
|
|
|
94
253
|
}
|
|
95
254
|
|
|
96
255
|
getProxyVideoSrc(src: string): string {
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
return src.indexOf('?') === -1 ? `${src}?${suffix}` : `${src}&${suffix}`;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
getVideoSrc(id: string): Promise<string> {
|
|
103
|
-
return new Promise((resolve, reject) => {
|
|
104
|
-
const token =
|
|
105
|
-
'Bearer <access_token>';
|
|
106
|
-
const endPoint = 'https://moviacloud.modusoperandi.com/movia/content';
|
|
107
|
-
|
|
108
|
-
(async () => {
|
|
109
|
-
// Video that will be fetched and appended
|
|
110
|
-
const remoteVidUrl = endPoint + '/id/' + id;
|
|
111
|
-
|
|
112
|
-
// Fetch remote URL, getting contents as binary blob
|
|
113
|
-
const vidBlob = await (
|
|
114
|
-
await fetch(remoteVidUrl, { headers: { Authorization: token } })
|
|
115
|
-
).blob();
|
|
116
|
-
|
|
117
|
-
const videoEle = document.createElement('video');
|
|
118
|
-
videoEle.src = URL.createObjectURL(vidBlob);
|
|
119
|
-
videoEle.addEventListener('loadedmetadata', function () {
|
|
120
|
-
resolve(videoEle.src);
|
|
121
|
-
});
|
|
122
|
-
})();
|
|
123
|
-
});
|
|
256
|
+
// eslint-disable-next-line
|
|
257
|
+
return getProxyImageSrc(src);
|
|
124
258
|
}
|
|
125
259
|
|
|
126
260
|
// Video Upload
|
|
@@ -128,51 +262,36 @@ class CustomLicitRuntime {
|
|
|
128
262
|
return true;
|
|
129
263
|
}
|
|
130
264
|
|
|
131
|
-
uploadVideo(blob: Object
|
|
265
|
+
uploadVideo(blob: Object): Promise<ImageLike> {
|
|
132
266
|
let img: ImageLike;
|
|
267
|
+
// Note: While looking at the uploadImage() function, it is found that a promise is resolved blindly after 3 seconds. Is it a
|
|
268
|
+
// requirement? If not, then I think it causes two issues, 1. Even if an image upload finishes in 700ms, it will take 3s for
|
|
269
|
+
// resolving the promise. 2. If the image upload takes more than 3s, then the promise will be incorrectly resolved before
|
|
270
|
+
// completing the upload.
|
|
271
|
+
// The following structure may be good to solve the issue.
|
|
133
272
|
return new Promise((resolve, reject) => {
|
|
134
273
|
// Use uploaded image URL.
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
'
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const remoteVidUrl = endPoint + '/id/' + id;
|
|
157
|
-
|
|
158
|
-
// Fetch remote URL, getting contents as binary blob
|
|
159
|
-
const vidBlob = await (
|
|
160
|
-
await fetch(remoteVidUrl, { headers: { Authorization: token } })
|
|
161
|
-
).blob();
|
|
162
|
-
|
|
163
|
-
const videoEle = document.createElement('video');
|
|
164
|
-
videoEle.src = URL.createObjectURL(vidBlob);
|
|
165
|
-
videoEle.addEventListener('loadedmetadata', function () {
|
|
166
|
-
img = {
|
|
167
|
-
id: id,
|
|
168
|
-
width: this.videoWidth,
|
|
169
|
-
height: this.videoHeight,
|
|
170
|
-
src: videoEle.src,
|
|
171
|
-
};
|
|
172
|
-
resolve(img);
|
|
173
|
-
});
|
|
174
|
-
})();
|
|
175
|
-
});
|
|
274
|
+
const url =
|
|
275
|
+
window.location.protocol +
|
|
276
|
+
'//' +
|
|
277
|
+
window.location.hostname +
|
|
278
|
+
':3004/saveimage?fn=' +
|
|
279
|
+
blob.name;
|
|
280
|
+
POST(url, blob, 'application/octet-stream').then(
|
|
281
|
+
(data) => {
|
|
282
|
+
img = JSON.parse(data);
|
|
283
|
+
resolve(img);
|
|
284
|
+
},
|
|
285
|
+
(err) => {
|
|
286
|
+
img = {
|
|
287
|
+
id: '',
|
|
288
|
+
width: 0,
|
|
289
|
+
height: 0,
|
|
290
|
+
src: '',
|
|
291
|
+
};
|
|
292
|
+
reject(img);
|
|
293
|
+
}
|
|
294
|
+
);
|
|
176
295
|
});
|
|
177
296
|
}
|
|
178
297
|
}
|
package/licit/client/index.js
CHANGED
|
@@ -335,7 +335,7 @@ function main(): void {
|
|
|
335
335
|
// To pass prosemirror plugins to editor pass it to plugins property which accept array of plugin object.
|
|
336
336
|
// null means no custom plugins to pass
|
|
337
337
|
// the plugin object must contain a method getEffectiveSchema() which accept schema and returns schema.
|
|
338
|
-
const plugins =
|
|
338
|
+
const plugins = [];
|
|
339
339
|
const runtime = new CustomLicitRuntime();
|
|
340
340
|
ReactDOM.render(
|
|
341
341
|
<Licit
|
|
@@ -343,7 +343,7 @@ function main(): void {
|
|
|
343
343
|
data={docJSON}
|
|
344
344
|
dataType={DataType.JSON}
|
|
345
345
|
debug={true}
|
|
346
|
-
docID={'
|
|
346
|
+
docID={''}
|
|
347
347
|
embedded={false}
|
|
348
348
|
height={'100vh'}
|
|
349
349
|
onChange={onChangeCB}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modusoperandi/licit",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.14",
|
|
4
4
|
"subversion": "1",
|
|
5
5
|
"description": "Rich text editor built with React and ProseMirror",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
|
|
57
57
|
"clean-webpack-plugin": "4.0.0",
|
|
58
58
|
"copy-webpack-plugin": "^11.0.0",
|
|
59
|
-
"css-loader": "
|
|
59
|
+
"css-loader": "6.7.3",
|
|
60
60
|
"enzyme": "^3.11.0",
|
|
61
61
|
"eslint": "^8.25.0",
|
|
62
62
|
"eslint-config-prettier": "^8.5.0",
|
|
@@ -70,12 +70,12 @@
|
|
|
70
70
|
"flow-webpack-plugin": "1.2.0",
|
|
71
71
|
"html-loader": "1.1.0",
|
|
72
72
|
"html-webpack-inline-source-plugin": "1.0.0-beta.2",
|
|
73
|
-
"html-webpack-plugin": "^
|
|
73
|
+
"html-webpack-plugin": "^5.5.0",
|
|
74
74
|
"husky": "^8.0.1",
|
|
75
75
|
"identity-obj-proxy": "^3.0.0",
|
|
76
76
|
"jest": "^29.2.0",
|
|
77
77
|
"jest-environment-jsdom": "^29.3.1",
|
|
78
|
-
"jest-prosemirror": "^
|
|
78
|
+
"jest-prosemirror": "^1.0.3",
|
|
79
79
|
"jest-sonar-reporter": "^2.0.0",
|
|
80
80
|
"lint-staged": "^13.0.3",
|
|
81
81
|
"mkdirp": "^1.0.4",
|
|
@@ -105,9 +105,7 @@
|
|
|
105
105
|
"node-mathquill": "0.10.2",
|
|
106
106
|
"prosemirror-collab": "1.2.2",
|
|
107
107
|
"prosemirror-dev-tools": "3.0.2",
|
|
108
|
-
"prosemirror-model": "~1.16.0",
|
|
109
108
|
"prosemirror-tables": "1.2.5",
|
|
110
|
-
"prosemirror-view": "1.27.0",
|
|
111
109
|
"query-string": "6.13.1",
|
|
112
110
|
"resize-observer-polyfill": "1.5.1",
|
|
113
111
|
"smooth-scroll-into-view-if-needed": "1.1.28",
|
|
@@ -13,6 +13,7 @@ import { createPopUp } from '@modusoperandi/licit-ui-commands';
|
|
|
13
13
|
import isElementFullyVisible from './ui/isElementFullyVisible';
|
|
14
14
|
|
|
15
15
|
import '@modusoperandi/licit-ui-commands/dist/ui/czi-pop-up.css';
|
|
16
|
+
import { CellSelection } from 'prosemirror-tables';
|
|
16
17
|
|
|
17
18
|
class TableCellTooltipView {
|
|
18
19
|
_cellElement: null;
|
|
@@ -41,9 +42,15 @@ class TableCellTooltipView {
|
|
|
41
42
|
|
|
42
43
|
let cellEl = domFound.node;
|
|
43
44
|
const popUp = this._popUp;
|
|
45
|
+
let actionNode = null;
|
|
46
|
+
if (result && state.selection instanceof CellSelection) {
|
|
47
|
+
actionNode = state.selection.$anchorCell.node(-1);
|
|
48
|
+
}
|
|
44
49
|
const viewPops = {
|
|
45
50
|
editorState: state,
|
|
46
51
|
editorView: view,
|
|
52
|
+
pluginView: this,
|
|
53
|
+
actionNode,
|
|
47
54
|
};
|
|
48
55
|
|
|
49
56
|
if (cellEl && !isElementFullyVisible(cellEl)) {
|
package/src/TableResizePlugin.js
CHANGED
|
@@ -595,9 +595,10 @@ export default class TableResizePlugin extends Plugin {
|
|
|
595
595
|
key: PLUGIN_KEY,
|
|
596
596
|
state: {
|
|
597
597
|
init(_: any, state: EditorState): ResizeState {
|
|
598
|
-
this.spec.props.nodeViews[
|
|
599
|
-
tableNodeTypes(state.schema).table.name
|
|
600
|
-
|
|
598
|
+
if (!this.spec.props.nodeViews['table']) {
|
|
599
|
+
this.spec.props.nodeViews[tableNodeTypes(state.schema).table.name] =
|
|
600
|
+
createTableView;
|
|
601
|
+
}
|
|
601
602
|
return new ResizeState(-1, null);
|
|
602
603
|
},
|
|
603
604
|
apply(tr: Transform, prev: EditorState): EditorState {
|
package/src/ui/TableCellMenu.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @flow
|
|
2
|
-
import { EditorState } from 'prosemirror-state';
|
|
2
|
+
import { EditorState, PluginView } from 'prosemirror-state';
|
|
3
3
|
import { EditorView } from 'prosemirror-view';
|
|
4
|
+
import { Node } from 'prosemirror-model';
|
|
4
5
|
import * as React from 'react';
|
|
5
6
|
|
|
6
7
|
import CommandMenuButton from './CommandMenuButton';
|
|
@@ -12,6 +13,8 @@ import './czi-table-cell-menu.css';
|
|
|
12
13
|
type Props = {
|
|
13
14
|
editorState: EditorState,
|
|
14
15
|
editorView: EditorView,
|
|
16
|
+
pluginView: PluginView,
|
|
17
|
+
actionNode: Node,
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
class TableCellMenu extends React.PureComponent<any, any> {
|
|
@@ -20,11 +23,21 @@ class TableCellMenu extends React.PureComponent<any, any> {
|
|
|
20
23
|
props: Props;
|
|
21
24
|
|
|
22
25
|
render(): React.Element<any> {
|
|
23
|
-
const { editorState, editorView } = this.props;
|
|
26
|
+
const { editorState, editorView, pluginView, actionNode } = this.props;
|
|
27
|
+
let cmdGrps = null;
|
|
28
|
+
|
|
29
|
+
if (pluginView.getMenu) {
|
|
30
|
+
cmdGrps = pluginView.getMenu(editorState, actionNode, TABLE_COMMANDS_GROUP);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!cmdGrps) {
|
|
34
|
+
cmdGrps = TABLE_COMMANDS_GROUP;
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
return (
|
|
25
38
|
<CommandMenuButton
|
|
26
39
|
className="czi-table-cell-menu"
|
|
27
|
-
commandGroups={
|
|
40
|
+
commandGroups={cmdGrps}
|
|
28
41
|
dispatch={editorView.dispatch}
|
|
29
42
|
editorState={editorState}
|
|
30
43
|
editorView={editorView}
|
|
@@ -4,8 +4,11 @@ import { fromHTMlElement } from '@modusoperandi/licit-ui-commands';
|
|
|
4
4
|
|
|
5
5
|
export default function isElementFullyVisible(el: HTMLElement): boolean {
|
|
6
6
|
const { x, y, w, h } = fromHTMlElement(el);
|
|
7
|
+
// to handle the rounded border scenario.
|
|
8
|
+
const factor = '10px' === el.style.borderRadius ? 3 : 1;
|
|
7
9
|
// Only checks the top-left point.
|
|
8
|
-
const nwEl =
|
|
10
|
+
const nwEl =
|
|
11
|
+
w && h ? el.ownerDocument.elementFromPoint(x + factor, y + factor) : null;
|
|
9
12
|
|
|
10
13
|
if (!nwEl) {
|
|
11
14
|
return false;
|
package/webpack.config.js
CHANGED
|
@@ -60,15 +60,7 @@ var options = {
|
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
test: /\.(woff(2)?|ttf|otf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
|
|
63
|
-
|
|
64
|
-
{
|
|
65
|
-
loader: 'file-loader',
|
|
66
|
-
options: {
|
|
67
|
-
name: '[name].[ext]',
|
|
68
|
-
outputPath: 'fonts/',
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
],
|
|
63
|
+
type: 'asset/resource',
|
|
72
64
|
},
|
|
73
65
|
{
|
|
74
66
|
test: /\.css$/,
|
|
@@ -93,10 +85,8 @@ var options = {
|
|
|
93
85
|
// jQuery (for Mathquill)
|
|
94
86
|
'window.jQuery': 'jquery',
|
|
95
87
|
}),
|
|
96
|
-
// type checker
|
|
97
|
-
|
|
98
|
-
// ? [new FlowWebpackPlugin({ flowArgs: ['--show-all-errors'] })]
|
|
99
|
-
// : []),
|
|
88
|
+
// type checker
|
|
89
|
+
... (isDev ? [new FlowWebpackPlugin({flowArgs: ['--show-all-errors']})] : []),
|
|
100
90
|
// clean the web folder
|
|
101
91
|
new CleanWebpackPlugin(),
|
|
102
92
|
// expose and write the allowed env vars on the compiled bundle
|