@pie-lib/editable-html-tip-tap 1.0.11 → 1.0.13

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.
@@ -57,10 +57,10 @@ export const buildExtensions = (activeExtensions, customExtensions, opts) => {
57
57
  addIf('superscript'),
58
58
  // icon should be modifies accordingly
59
59
  addIf('subscript'),
60
- addIf('image', imagePlugin),
60
+ addIf('image', !!imagePlugin),
61
61
  addIf('video'),
62
62
  addIf('audio'),
63
- addIf('math', mathPlugin),
63
+ addIf('math', !!mathPlugin),
64
64
  ...languageCharactersPlugins.map((plugin) => addIf('languageCharacters', plugin)),
65
65
  addIf('text-align'),
66
66
  addIf('blockquote'),
@@ -69,8 +69,8 @@ export const buildExtensions = (activeExtensions, customExtensions, opts) => {
69
69
  addIf('numbered-list'),
70
70
  addIf('undo'),
71
71
  addIf('redo'),
72
- addIf('responseArea', respAreaPlugin),
73
- addIf('css', cssPlugin),
72
+ addIf('responseArea', !!respAreaPlugin),
73
+ addIf('css', !!cssPlugin),
74
74
  addIf('html', !!opts.html),
75
75
  ]);
76
76
  };
@@ -1,4 +1,5 @@
1
1
  import React, { useState, useEffect, useRef } from 'react';
2
+ import ReactDOM from 'react-dom';
2
3
  import { Extension, Node, mergeAttributes } from '@tiptap/core';
3
4
  import { NodeViewWrapper, ReactRenderer, ReactNodeViewRenderer } from '@tiptap/react';
4
5
  import { Plugin, PluginKey, NodeSelection, TextSelection } from 'prosemirror-state';
@@ -118,7 +119,6 @@ export const MathNode = Node.create({
118
119
  addCommands() {
119
120
  return {
120
121
  insertMath: (latex = '') => ({ tr, editor, dispatch }) => {
121
- // 2) Now the editor.view.state reflects the insertion
122
122
  const { state } = editor.view;
123
123
  const node = state.schema.nodes.math.create({
124
124
  latex,
@@ -172,6 +172,7 @@ export const MathNodeView = (props) => {
172
172
  const { node, updateAttributes, editor, selected, options } = props;
173
173
  const [showToolbar, setShowToolbar] = useState(selected);
174
174
  const toolbarRef = useRef(null);
175
+ const [position, setPosition] = useState({ top: 0, left: 0 });
175
176
 
176
177
  const latex = node.attrs.latex || '';
177
178
 
@@ -186,6 +187,15 @@ export const MathNodeView = (props) => {
186
187
  }, [showToolbar]);
187
188
 
188
189
  useEffect(() => {
190
+ // Calculate position relative to selection
191
+ const bodyRect = document.body.getBoundingClientRect();
192
+ const { from } = editor.state.selection;
193
+ const start = editor.view.coordsAtPos(from);
194
+ setPosition({
195
+ top: start.top + Math.abs(bodyRect.top) + 40, // shift above
196
+ left: start.left,
197
+ });
198
+
189
199
  const handleClickOutside = (event) => {
190
200
  if (
191
201
  toolbarRef.current &&
@@ -203,7 +213,7 @@ export const MathNodeView = (props) => {
203
213
  }
204
214
 
205
215
  return () => document.removeEventListener('mousedown', handleClickOutside);
206
- }, [showToolbar]);
216
+ }, [editor, showToolbar]);
207
217
 
208
218
  const handleChange = (newLatex) => {
209
219
  updateAttributes({ latex: newLatex });
@@ -237,23 +247,24 @@ export const MathNodeView = (props) => {
237
247
  <div onClick={() => setShowToolbar(true)} contentEditable={false}>
238
248
  <MathPreview latex={latex} />
239
249
  </div>
240
-
241
- {showToolbar && (
242
- <div
243
- ref={toolbarRef}
244
- style={{
245
- position: 'absolute',
246
- top: '100%',
247
- left: 0,
248
- zIndex: 20,
249
- background: 'var(--editable-html-toolbar-bg, #efefef)',
250
- boxShadow:
251
- '0px 1px 5px 0px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.12)',
252
- }}
253
- >
254
- <MathToolbar latex={latex} autoFocus onChange={handleChange} onDone={handleDone} keypadMode="basic" />
255
- </div>
256
- )}
250
+ {showToolbar &&
251
+ ReactDOM.createPortal(
252
+ <div
253
+ ref={toolbarRef}
254
+ style={{
255
+ position: 'absolute',
256
+ top: `${position.top}px`,
257
+ left: `${position.left}px`,
258
+ zIndex: 20,
259
+ background: 'var(--editable-html-toolbar-bg, #efefef)',
260
+ boxShadow:
261
+ '0px 1px 5px 0px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.12)',
262
+ }}
263
+ >
264
+ <MathToolbar latex={latex} autoFocus onChange={handleChange} onDone={handleDone} keypadMode="basic" />
265
+ </div>,
266
+ document.body,
267
+ )}
257
268
  </NodeViewWrapper>
258
269
  );
259
270
  };
@@ -1,12 +1,9 @@
1
- // InlineNodes.js
2
1
  import React from 'react';
3
2
  import { Node, ReactNodeViewRenderer, ReactRenderer } from '@tiptap/react';
4
3
  import ExplicitConstructedResponse from '../components/respArea/ExplicitConstructedResponse';
5
4
  import DragInTheBlank from '../components/respArea/DragInTheBlank/DragInTheBlank';
6
5
  import InlineDropdown from '../components/respArea/InlineDropdown';
7
6
  import { Extension } from '@tiptap/core';
8
- import { MathToolbar } from '@pie-lib/math-toolbar';
9
- import tippy from 'tippy.js';
10
7
 
11
8
  export const ResponseAreaExtension = Extension.create({
12
9
  name: 'responseArea',
@@ -120,36 +120,6 @@ const styles = (theme) => ({
120
120
  overflowY: 'auto',
121
121
  color: color.text(),
122
122
  backgroundColor: color.background(),
123
- '&::before': {
124
- left: '0',
125
- right: '0',
126
- bottom: '0',
127
- height: '1px',
128
- content: '""',
129
- position: 'absolute',
130
- transition: 'background-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
131
- pointerEvents: 'none',
132
- backgroundColor: 'rgba(0, 0, 0, 0.42)',
133
- },
134
- '&::after': {
135
- left: '0',
136
- right: '0',
137
- bottom: '0',
138
- height: '1px',
139
- content: '""',
140
- position: 'absolute',
141
- transform: 'scaleX(0)',
142
- transition: 'transform 200ms cubic-bezier(0.0, 0.0, 0.2, 1) 0ms, background-color 200ms linear',
143
- backgroundColor: 'rgba(0, 0, 0, 0.42)',
144
- },
145
- },
146
- disabledUnderline: {
147
- '&::before': {
148
- display: 'none',
149
- },
150
- '&::after': {
151
- display: 'none',
152
- },
153
123
  },
154
124
  disabledScrollbar: {
155
125
  '&::-webkit-scrollbar': {
@@ -158,33 +128,6 @@ const styles = (theme) => ({
158
128
  scrollbarWidth: 'none',
159
129
  '-ms-overflow-style': 'none',
160
130
  },
161
- readOnly: {
162
- '&::before': {
163
- background: 'transparent',
164
- backgroundSize: '5px 1px',
165
- backgroundImage: 'linear-gradient(to right, rgba(0, 0, 0, 0.42) 33%, transparent 0%)',
166
- backgroundRepeat: 'repeat-x',
167
- backgroundPosition: 'left top',
168
- },
169
- '&::after': {
170
- left: '0',
171
- right: '0',
172
- bottom: '0',
173
- height: '1px',
174
- content: '""',
175
- position: 'absolute',
176
- transform: 'scaleX(0)',
177
- transition: 'transform 200ms cubic-bezier(0.0, 0.0, 0.2, 1) 0ms, background-color 0ms linear',
178
- backgroundColor: 'rgba(0, 0, 0, 0)',
179
- },
180
- '&:hover': {
181
- '&::after': {
182
- transform: 'scaleX(0)',
183
- backgroundColor: theme.palette.common.black,
184
- height: '2px',
185
- },
186
- },
187
- },
188
131
  error: {
189
132
  border: `2px solid ${theme.palette.error.main} !important`,
190
133
  },