@pie-lib/editable-html-tip-tap 2.1.19 → 2.1.20-beta.10

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 (84) hide show
  1. package/CHANGELOG.md +0 -130
  2. package/lib/__tests__/EditableHtml.test.js +831 -0
  3. package/lib/__tests__/constants.test.js +21 -0
  4. package/lib/__tests__/div-to-paragraph-conversion.test.js +213 -0
  5. package/lib/__tests__/extensions.test.js +209 -0
  6. package/lib/__tests__/index.test.js +250 -0
  7. package/lib/__tests__/size-utils.test.js +57 -0
  8. package/lib/__tests__/spellcheck.test.js +142 -0
  9. package/lib/__tests__/theme.test.js +17 -0
  10. package/lib/components/EditableHtml.js +0 -56
  11. package/lib/components/EditableHtml.js.map +1 -1
  12. package/lib/components/MenuBar.js +12 -81
  13. package/lib/components/MenuBar.js.map +1 -1
  14. package/lib/components/TiptapContainer.js +2 -2
  15. package/lib/components/TiptapContainer.js.map +1 -1
  16. package/lib/components/__tests__/AltDialog.test.js +201 -0
  17. package/lib/components/__tests__/CharacterPicker.test.js +455 -0
  18. package/lib/components/__tests__/CssIcon.test.js +58 -0
  19. package/lib/components/__tests__/DragInTheBlank.test.js +295 -0
  20. package/lib/components/__tests__/ExplicitConstructedResponse.test.js +345 -0
  21. package/lib/components/__tests__/ImageToolbar.test.js +185 -0
  22. package/lib/components/__tests__/InlineDropdown.test.js +839 -0
  23. package/lib/components/__tests__/InsertImageHandler.test.js +171 -0
  24. package/lib/components/__tests__/MediaDialog.test.js +433 -0
  25. package/lib/components/__tests__/MediaToolbar.test.js +126 -0
  26. package/lib/components/__tests__/MediaWrapper.test.js +96 -0
  27. package/lib/components/__tests__/MenuBar.test.js +502 -0
  28. package/lib/components/__tests__/RespArea.test.js +171 -0
  29. package/lib/components/__tests__/TableIcons.test.js +153 -0
  30. package/lib/components/__tests__/TextAlign.test.js +209 -0
  31. package/lib/components/__tests__/TiptapContainer.test.js +196 -0
  32. package/lib/components/__tests__/characterUtils.test.js +178 -0
  33. package/lib/components/__tests__/choice.test.js +213 -0
  34. package/lib/components/__tests__/custom-popper.test.js +108 -0
  35. package/lib/components/__tests__/done-button.test.js +72 -0
  36. package/lib/components/__tests__/toolbar-buttons.test.js +277 -0
  37. package/lib/components/common/toolbar-buttons.js +5 -6
  38. package/lib/components/common/toolbar-buttons.js.map +1 -1
  39. package/lib/components/icons/TableIcons.js +1 -3
  40. package/lib/components/icons/TableIcons.js.map +1 -1
  41. package/lib/components/icons/TextAlign.js +5 -14
  42. package/lib/components/icons/TextAlign.js.map +1 -1
  43. package/lib/components/respArea/DragInTheBlank/__tests__/choice.test.js +90 -0
  44. package/lib/components/respArea/MathTemplated.js +8 -14
  45. package/lib/components/respArea/MathTemplated.js.map +1 -1
  46. package/lib/components/respArea/__tests__/MathTemplated.test.js +217 -0
  47. package/lib/extensions/__tests__/css.test.js +214 -0
  48. package/lib/extensions/__tests__/custom-toolbar-wrapper.test.js +175 -0
  49. package/lib/extensions/__tests__/divNode.test.js +108 -0
  50. package/lib/extensions/__tests__/ensure-empty-root-div.test.js +50 -0
  51. package/lib/extensions/__tests__/ensure-list-item-content-is-div.test.js +60 -0
  52. package/lib/extensions/__tests__/extended-list-item.test.js +13 -0
  53. package/lib/extensions/__tests__/extended-table-cell.test.js +15 -0
  54. package/lib/extensions/__tests__/extended-table.test.js +200 -0
  55. package/lib/extensions/__tests__/image-component.test.js +432 -0
  56. package/lib/extensions/__tests__/image.test.js +313 -0
  57. package/lib/extensions/__tests__/math.test.js +1411 -0
  58. package/lib/extensions/__tests__/media-node-view.test.js +307 -0
  59. package/lib/extensions/__tests__/media.test.js +292 -0
  60. package/lib/extensions/__tests__/responseArea.test.js +736 -0
  61. package/lib/extensions/math.js +37 -19
  62. package/lib/extensions/math.js.map +1 -1
  63. package/lib/styles/editorContainerStyles.js +2 -2
  64. package/lib/styles/editorContainerStyles.js.map +1 -1
  65. package/lib/utils/__tests__/helper.test.js +107 -0
  66. package/lib/utils/__tests__/toolbar.test.js +38 -0
  67. package/package.json +9 -9
  68. package/src/__tests__/EditableHtml.test.jsx +0 -80
  69. package/src/components/EditableHtml.jsx +0 -52
  70. package/src/components/MenuBar.jsx +9 -91
  71. package/src/components/TiptapContainer.jsx +2 -2
  72. package/src/components/__tests__/MenuBar.test.jsx +9 -97
  73. package/src/components/__tests__/toolbar-buttons.test.jsx +2 -15
  74. package/src/components/common/toolbar-buttons.jsx +4 -6
  75. package/src/components/icons/TableIcons.jsx +1 -9
  76. package/src/components/icons/TextAlign.jsx +5 -39
  77. package/src/components/respArea/MathTemplated.jsx +6 -13
  78. package/src/components/respArea/__tests__/MathTemplated.test.jsx +1 -1
  79. package/src/extensions/__tests__/math.test.js +11 -9
  80. package/src/extensions/math.js +19 -11
  81. package/src/styles/editorContainerStyles.js +2 -2
  82. package/LICENSE.md +0 -5
  83. package/src/__tests__/editor-attributes.test.jsx +0 -77
  84. package/src/__tests__/spellcheck.test.jsx +0 -63
@@ -1,20 +1,7 @@
1
1
  import React from 'react';
2
2
  import { fireEvent, render } from '@testing-library/react';
3
- import { color } from '@pie-lib/render-ui';
4
3
  import { Button, MarkButton, RawButton, RawMarkButton } from '../common/toolbar-buttons';
5
4
 
6
- /*
7
- * jsdom does not resolve custom properties, so toHaveStyle() normalises `var(--x, y)`
8
- * to the empty string and cannot compare it. These buttons now take their ink from
9
- * `--pie-text`, so assert against the rule emotion emitted for the element's class.
10
- */
11
- const declaredColor = (el) =>
12
- Array.from(document.querySelectorAll('style'))
13
- .flatMap((tag) => Array.from(tag.sheet?.cssRules || []))
14
- .filter((rule) => Array.from(el.classList).some((c) => rule.selectorText?.includes(`.${c}`)))
15
- .map((rule) => rule.style?.color)
16
- .find(Boolean);
17
-
18
5
  describe('RawButton', () => {
19
6
  it('renders without crashing', () => {
20
7
  const { container } = render(<RawButton onClick={jest.fn()}>Click me</RawButton>);
@@ -71,7 +58,7 @@ describe('RawButton', () => {
71
58
  </RawButton>,
72
59
  );
73
60
  const button = getByText('Active');
74
- expect(declaredColor(button)).toBe(color.text());
61
+ expect(button).toHaveStyle({ color: 'black' });
75
62
  });
76
63
 
77
64
  it('applies disabled style when disabled is true', () => {
@@ -209,7 +196,7 @@ describe('RawMarkButton', () => {
209
196
  </RawMarkButton>,
210
197
  );
211
198
  const button = getByText('B');
212
- expect(declaredColor(button)).toBe(color.text());
199
+ expect(button).toHaveStyle({ color: 'black' });
213
200
  });
214
201
 
215
202
  it('has aria-label from label prop', () => {
@@ -2,12 +2,11 @@ import React from 'react';
2
2
  import debug from 'debug';
3
3
  import { styled } from '@mui/material/styles';
4
4
  import PropTypes from 'prop-types';
5
- import { color } from '@pie-lib/render-ui';
6
5
 
7
6
  const StyledButton = styled('button', {
8
7
  shouldForwardProp: (prop) => !['active', 'disabled', 'extraStyles'].includes(prop),
9
- })(({ active, disabled }) => ({
10
- color: active ? color.text() : color.disabled(),
8
+ })(({ theme, active, disabled }) => ({
9
+ color: active ? 'black' : 'grey',
11
10
  display: 'inline-flex',
12
11
  padding: '2px',
13
12
  background: 'none',
@@ -19,11 +18,10 @@ const StyledButton = styled('button', {
19
18
  height: '24px',
20
19
  },
21
20
  '&:hover': {
22
- color: disabled ? color.disabled() : color.text(),
21
+ color: disabled ? 'grey' : 'black',
23
22
  },
24
23
  '&:focus': {
25
- // See MenuBar: the focus ring takes the registered focus token, not a grey.
26
- outline: `2px solid ${color.buttonFocusOutline()}`,
24
+ outline: `2px solid ${theme.palette.grey[700]}`,
27
25
  },
28
26
  ...(disabled && {
29
27
  opacity: 0.7,
@@ -10,15 +10,7 @@ const StyledPath = styled('path')({
10
10
 
11
11
  const SvgIcon = (Component) => {
12
12
  return (props) => (
13
- <svg
14
- xmlns="http://www.w3.org/2000/svg"
15
- version="1.1"
16
- width="24"
17
- height="24"
18
- viewBox="0 0 24 24"
19
- aria-hidden="true"
20
- focusable="false"
21
- >
13
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="24" height="24" viewBox="0 0 24 24">
22
14
  <Component {...props} />
23
15
  </svg>
24
16
  );
@@ -4,15 +4,7 @@ import List from '@mui/material/List';
4
4
  import ListItem from '@mui/material/ListItem';
5
5
 
6
6
  export const AlignLeft = () => (
7
- <svg
8
- width="20"
9
- height="20"
10
- viewBox="0 0 66 66"
11
- fill="none"
12
- xmlns="http://www.w3.org/2000/svg"
13
- aria-hidden="true"
14
- focusable="false"
15
- >
7
+ <svg width="20" height="20" viewBox="0 0 66 66" fill="none" xmlns="http://www.w3.org/2000/svg">
16
8
  <path
17
9
  d="M42.1875 4.75C42.1875 7.38672 39.9902 9.4375 37.5 9.4375H4.6875C2.05078 9.4375 0 7.38672 0 4.75C0 2.25977 2.05078 0.0625 4.6875 0.0625H37.5C39.9902 0.0625 42.1875 2.25977 42.1875 4.75ZM42.1875 42.25C42.1875 44.8867 39.9902 46.9375 37.5 46.9375H4.6875C2.05078 46.9375 0 44.8867 0 42.25C0 39.7598 2.05078 37.5625 4.6875 37.5625H37.5C39.9902 37.5625 42.1875 39.7598 42.1875 42.25ZM0 23.5C0 21.0098 2.05078 18.8125 4.6875 18.8125H60.9375C63.4277 18.8125 65.625 21.0098 65.625 23.5C65.625 26.1367 63.4277 28.1875 60.9375 28.1875H4.6875C2.05078 28.1875 0 26.1367 0 23.5ZM65.625 61C65.625 63.6367 63.4277 65.6875 60.9375 65.6875H4.6875C2.05078 65.6875 0 63.6367 0 61C0 58.5098 2.05078 56.3125 4.6875 56.3125H60.9375C63.4277 56.3125 65.625 58.5098 65.625 61Z"
18
10
  fill="currentColor"
@@ -21,15 +13,7 @@ export const AlignLeft = () => (
21
13
  );
22
14
 
23
15
  export const AlignRight = () => (
24
- <svg
25
- width="20"
26
- height="20"
27
- viewBox="0 0 66 66"
28
- fill="none"
29
- xmlns="http://www.w3.org/2000/svg"
30
- aria-hidden="true"
31
- focusable="false"
32
- >
16
+ <svg width="20" height="20" viewBox="0 0 66 66" fill="none" xmlns="http://www.w3.org/2000/svg">
33
17
  <path
34
18
  d="M65.625 4.75C65.625 7.38672 63.4277 9.4375 60.9375 9.4375H28.125C25.4883 9.4375 23.4375 7.38672 23.4375 4.75C23.4375 2.25977 25.4883 0.0625 28.125 0.0625H60.9375C63.4277 0.0625 65.625 2.25977 65.625 4.75ZM65.625 42.25C65.625 44.8867 63.4277 46.9375 60.9375 46.9375H28.125C25.4883 46.9375 23.4375 44.8867 23.4375 42.25C23.4375 39.7598 25.4883 37.5625 28.125 37.5625H60.9375C63.4277 37.5625 65.625 39.7598 65.625 42.25ZM0 23.5C0 21.0098 2.05078 18.8125 4.6875 18.8125H60.9375C63.4277 18.8125 65.625 21.0098 65.625 23.5C65.625 26.1367 63.4277 28.1875 60.9375 28.1875H4.6875C2.05078 28.1875 0 26.1367 0 23.5ZM65.625 61C65.625 63.6367 63.4277 65.6875 60.9375 65.6875H4.6875C2.05078 65.6875 0 63.6367 0 61C0 58.5098 2.05078 56.3125 4.6875 56.3125H60.9375C63.4277 56.3125 65.625 58.5098 65.625 61Z"
35
19
  fill="currentColor"
@@ -38,15 +22,7 @@ export const AlignRight = () => (
38
22
  );
39
23
 
40
24
  export const AlignCenter = () => (
41
- <svg
42
- width="20"
43
- height="20"
44
- viewBox="0 0 66 66"
45
- fill="none"
46
- xmlns="http://www.w3.org/2000/svg"
47
- aria-hidden="true"
48
- focusable="false"
49
- >
25
+ <svg width="20" height="20" viewBox="0 0 66 66" fill="none" xmlns="http://www.w3.org/2000/svg">
50
26
  <path
51
27
  d="M51.5625 4.75C51.5625 7.38672 49.3652 9.4375 46.875 9.4375H18.75C16.1133 9.4375 14.0625 7.38672 14.0625 4.75C14.0625 2.25977 16.1133 0.0625 18.75 0.0625H46.875C49.3652 0.0625 51.5625 2.25977 51.5625 4.75ZM65.625 23.5C65.625 26.1367 63.4277 28.1875 60.9375 28.1875H4.6875C2.05078 28.1875 0 26.1367 0 23.5C0 21.0098 2.05078 18.8125 4.6875 18.8125H60.9375C63.4277 18.8125 65.625 21.0098 65.625 23.5ZM0 61C0 58.5098 2.05078 56.3125 4.6875 56.3125H60.9375C63.4277 56.3125 65.625 58.5098 65.625 61C65.625 63.6367 63.4277 65.6875 60.9375 65.6875H4.6875C2.05078 65.6875 0 63.6367 0 61ZM51.5625 42.25C51.5625 44.8867 49.3652 46.9375 46.875 46.9375H18.75C16.1133 46.9375 14.0625 44.8867 14.0625 42.25C14.0625 39.7598 16.1133 37.5625 18.75 37.5625H46.875C49.3652 37.5625 51.5625 39.7598 51.5625 42.25Z"
52
28
  fill="currentColor"
@@ -55,15 +31,7 @@ export const AlignCenter = () => (
55
31
  );
56
32
 
57
33
  export const AlignJustify = () => (
58
- <svg
59
- width="20"
60
- height="20"
61
- viewBox="0 0 66 66"
62
- fill="none"
63
- xmlns="http://www.w3.org/2000/svg"
64
- aria-hidden="true"
65
- focusable="false"
66
- >
34
+ <svg width="20" height="20" viewBox="0 0 66 66" fill="none" xmlns="http://www.w3.org/2000/svg">
67
35
  <path
68
36
  d="M65.625 4.75C65.625 7.38672 63.4277 9.4375 60.9375 9.4375H4.6875C2.05078 9.4375 0 7.38672 0 4.75C0 2.25977 2.05078 0.0625 4.6875 0.0625H60.9375C63.4277 0.0625 65.625 2.25977 65.625 4.75ZM65.625 42.25C65.625 44.8867 63.4277 46.9375 60.9375 46.9375H4.6875C2.05078 46.9375 0 44.8867 0 42.25C0 39.7598 2.05078 37.5625 4.6875 37.5625H60.9375C63.4277 37.5625 65.625 39.7598 65.625 42.25ZM0 23.5C0 21.0098 2.05078 18.8125 4.6875 18.8125H60.9375C63.4277 18.8125 65.625 21.0098 65.625 23.5C65.625 26.1367 63.4277 28.1875 60.9375 28.1875H4.6875C2.05078 28.1875 0 26.1367 0 23.5ZM65.625 61C65.625 63.6367 63.4277 65.6875 60.9375 65.6875H4.6875C2.05078 65.6875 0 63.6367 0 61C0 58.5098 2.05078 56.3125 4.6875 56.3125H60.9375C63.4277 56.3125 65.625 58.5098 65.625 61Z"
69
37
  fill="currentColor"
@@ -111,9 +79,7 @@ export default ({ editor, onChange }) => {
111
79
  <div>
112
80
  <div style={{ display: 'flex', alignItems: 'center' }} onClick={onMouseDown}>
113
81
  {icon}
114
- <span style={{ marginLeft: '5px', fontSize: '8px' }} aria-hidden="true">
115
- &#9660;
116
- </span>
82
+ <span style={{ marginLeft: '5px', fontSize: '8px' }}>&#9660;</span>
117
83
  </div>
118
84
  <Collapse in={open} timeout="auto" unmountOnExit style={{ position: 'absolute' }}>
119
85
  <List
@@ -1,18 +1,12 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { NodeViewWrapper } from '@tiptap/react';
4
- import { mq } from '@pie-lib/math-input';
4
+ import { mq } from '@pie-lib/math-input-mathlive';
5
5
  import { styled } from '@mui/material/styles';
6
- import { color } from '@pie-lib/render-ui';
7
6
 
8
7
  const StyledSpanContainer = styled('span')(() => ({
9
8
  display: 'inline-flex',
10
- /*
11
- * #C0C3CF is `--pie-blue-grey-300`'s default value, but that token is a fill: it
12
- * measures 1.00:1 against black-on-rose's own background. The box outline is what
13
- * marks the response slot in running text, so it takes the stroke token instead.
14
- */
15
- border: `1px solid ${color.border()}`,
9
+ border: '1px solid #C0C3CF',
16
10
  margin: '1px 5px',
17
11
  cursor: 'pointer',
18
12
  alignItems: 'center',
@@ -22,12 +16,11 @@ const StyledSpanContainer = styled('span')(() => ({
22
16
  height: 'fit-content',
23
17
  }));
24
18
 
25
- const StyledResponseBox = styled('div')(() => ({
26
- // Fill and ink move together so the label stays legible on whatever the fill becomes.
27
- background: color.backgroundDark(),
28
- color: color.text(),
19
+ const StyledResponseBox = styled('div')(({ theme }) => ({
20
+ background: theme.palette.grey['A100'],
21
+ color: theme.palette.grey['A700'],
29
22
  display: 'inline-flex',
30
- borderRight: `2px solid ${color.border()}`,
23
+ borderRight: '2px solid #C0C3CF',
31
24
  boxSizing: 'border-box',
32
25
  overflow: 'hidden',
33
26
  fontSize: '12px',
@@ -11,7 +11,7 @@ jest.mock('@tiptap/react', () => ({
11
11
  ),
12
12
  }));
13
13
 
14
- jest.mock('@pie-lib/math-input', () => ({
14
+ jest.mock('@pie-lib/math-input-mathlive', () => ({
15
15
  mq: {
16
16
  Static: ({ latex }) => (
17
17
  <div data-testid="mq-static" data-latex={latex}>
@@ -765,11 +765,13 @@ describe('MathNodeView', () => {
765
765
  dateNowSpy.mockRestore();
766
766
  });
767
767
 
768
+ // The wrapper is an emotion styled() component, so className also carries
769
+ // emotion's generated class - assert on the math-node token, not equality.
768
770
  it('assigns a timestamp-based class to NodeViewWrapper', () => {
769
771
  const { getByTestId } = render(<MathNodeView {...defaultProps} />);
770
772
  const wrapper = getByTestId('node-view-wrapper');
771
773
 
772
- expect(wrapper.className).toMatch(/^math-node-\d+$/);
774
+ expect(Array.from(wrapper.classList).some((c) => /^math-node-\d+$/.test(c))).toBe(true);
773
775
  });
774
776
 
775
777
  it('assigns a different class to each MathNodeView instance', () => {
@@ -781,8 +783,12 @@ describe('MathNodeView', () => {
781
783
  );
782
784
 
783
785
  const wrappers = getAllByTestId('node-view-wrapper');
784
- expect(wrappers[0].className).toBe('math-node-1000');
785
- expect(wrappers[1].className).toBe('math-node-1001');
786
+ const mathNodeClass = (el) => Array.from(el.classList).find((c) => c.startsWith('math-node-'));
787
+
788
+ expect(mathNodeClass(wrappers[0])).toBe('math-node-1000');
789
+ expect(mathNodeClass(wrappers[1])).toBe('math-node-1001');
790
+ // and they must differ
791
+ expect(mathNodeClass(wrappers[0])).not.toBe(mathNodeClass(wrappers[1]));
786
792
  });
787
793
 
788
794
  it('closes toolbar when clicking a different math node', async () => {
@@ -835,9 +841,7 @@ describe('MathNodeView', () => {
835
841
  },
836
842
  };
837
843
 
838
- const { queryByTestId, rerender } = render(
839
- <MathNodeView {...defaultProps} editor={editor} selected={false} />,
840
- );
844
+ const { queryByTestId, rerender } = render(<MathNodeView {...defaultProps} editor={editor} selected={false} />);
841
845
  rerender(<MathNodeView {...defaultProps} editor={editor} selected={true} />);
842
846
 
843
847
  await act(async () => {});
@@ -853,9 +857,7 @@ describe('MathNodeView', () => {
853
857
  },
854
858
  };
855
859
 
856
- const { queryByTestId, rerender } = render(
857
- <MathNodeView {...defaultProps} editor={editor} selected={false} />,
858
- );
860
+ const { queryByTestId, rerender } = render(<MathNodeView {...defaultProps} editor={editor} selected={false} />);
859
861
  rerender(<MathNodeView {...defaultProps} editor={editor} selected={true} />);
860
862
 
861
863
  await act(async () => {});
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom';
3
3
  import { Node } from '@tiptap/core';
4
4
  import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';
5
5
  import { NodeSelection, Plugin, PluginKey, TextSelection } from 'prosemirror-state';
6
+ import { styled } from '@mui/material/styles';
6
7
  import { MathPreview, MathToolbar } from '@pie-lib/math-toolbar';
7
8
  import { wrapMath } from '@pie-lib/math-rendering';
8
9
  import { setToolbarOpened } from '../utils/toolbar';
@@ -116,6 +117,21 @@ export const ZeroWidthSpaceHandlingPlugin = new Plugin({
116
117
  },
117
118
  });
118
119
 
120
+ const StyledMathNodeWrapper = styled(NodeViewWrapper, {
121
+ shouldForwardProp: (prop) => prop !== 'selected',
122
+ })(({ theme, selected }) => ({
123
+ display: 'inline-flex',
124
+ cursor: 'pointer',
125
+ margin: '0 4px',
126
+ '&:not(:has(.ML__latex))': {
127
+ border: 'solid 1px lightgrey',
128
+ padding: '5px',
129
+ },
130
+ ...(selected && {
131
+ border: `solid 1px ${theme.palette.primary.main}`,
132
+ }),
133
+ }));
134
+
119
135
  export const MathNode = Node.create({
120
136
  name: 'math',
121
137
  group: 'inline',
@@ -400,17 +416,9 @@ export const MathNodeView = (props) => {
400
416
  }, [editor, showToolbar, node]);
401
417
 
402
418
  return (
403
- <NodeViewWrapper
404
- className={`math-node-${timestamp.current}`}
405
- style={{
406
- display: 'inline-flex',
407
- cursor: 'pointer',
408
- margin: '0 4px',
409
- }}
410
- data-selected={selected}
411
- >
419
+ <StyledMathNodeWrapper className={`math-node-${timestamp.current}`} selected={selected} data-selected={selected}>
412
420
  <div ref={nodeRef} onClick={() => setShowToolbar(true)} contentEditable={false}>
413
- <MathPreview latex={latex} />
421
+ <MathPreview latex={latex} isSelected={selected} outlineOnWrapper />
414
422
  </div>
415
423
  {showToolbar &&
416
424
  ReactDOM.createPortal(
@@ -441,6 +449,6 @@ export const MathNodeView = (props) => {
441
449
  </div>,
442
450
  editor?._tiptapContainerEl || document.body,
443
451
  )}
444
- </NodeViewWrapper>
452
+ </StyledMathNodeWrapper>
445
453
  );
446
454
  };
@@ -101,14 +101,14 @@ const styles = (theme) => ({
101
101
  backgroundColor: color.background(),
102
102
  },
103
103
  '& table:not([border="1"]) tr': {
104
- borderTop: `1px solid ${color.tableGridLight()}`,
104
+ borderTop: '1px solid #dfe2e5',
105
105
  },
106
106
  '& td, th': {
107
107
  padding: '.6em 1em',
108
108
  textAlign: 'center',
109
109
  },
110
110
  '& table:not([border="1"]) td, th': {
111
- border: `1px solid ${color.tableGridLight()}`,
111
+ border: '1px solid #dfe2e5',
112
112
  },
113
113
  },
114
114
  children: {
package/LICENSE.md DELETED
@@ -1,5 +0,0 @@
1
- Copyright 2019 CoreSpring Inc
2
-
3
- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4
-
5
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -1,77 +0,0 @@
1
- import React from 'react';
2
- import { render, waitFor } from '@testing-library/react';
3
- import { EditableHtml } from '../components/EditableHtml';
4
-
5
- const renderEditor = (props) =>
6
- render(<EditableHtml markup="<p>hello</p>" onChange={() => {}} pluginProps={{}} {...props} />);
7
-
8
- const prosemirror = (container) => container.querySelector('.ProseMirror');
9
-
10
- const waitForEditor = async (container) => {
11
- await waitFor(() => {
12
- expect(prosemirror(container)).toBeInTheDocument();
13
- });
14
- };
15
-
16
- describe('contenteditable attributes', () => {
17
- // PIE-1015: 2.1.17 lost role="textbox" on a plain mount, because setEditable re-pushes
18
- // editorProps through setOptions and ProseMirror drops any attribute no longer listed.
19
- it('announces the editor as a textbox on a plain mount', async () => {
20
- const { container } = renderEditor();
21
-
22
- await waitForEditor(container);
23
-
24
- expect(prosemirror(container).getAttribute('role')).toBe('textbox');
25
- });
26
-
27
- // PIE-1016: a PIE-owned hook external consumers can target, unlike role or .tiptap.ProseMirror.
28
- it('exposes the PIE-owned editor hook on a plain mount', async () => {
29
- const { container } = renderEditor();
30
-
31
- await waitForEditor(container);
32
-
33
- expect(prosemirror(container).getAttribute('data-pie-editor')).toBe('true');
34
- });
35
-
36
- it('keeps both attributes when spellCheck changes on a mounted editor', async () => {
37
- const { container, rerender } = renderEditor({ spellCheck: true });
38
-
39
- await waitForEditor(container);
40
-
41
- rerender(<EditableHtml markup="<p>hello</p>" onChange={() => {}} pluginProps={{}} spellCheck={false} />);
42
-
43
- await waitFor(() => {
44
- expect(prosemirror(container).getAttribute('spellcheck')).toBe('false');
45
- });
46
-
47
- expect(prosemirror(container).getAttribute('role')).toBe('textbox');
48
- expect(prosemirror(container).getAttribute('data-pie-editor')).toBe('true');
49
- });
50
-
51
- it('keeps both attributes when the editor is disabled on a mounted editor', async () => {
52
- const { container, rerender } = renderEditor();
53
-
54
- await waitForEditor(container);
55
-
56
- rerender(<EditableHtml markup="<p>hello</p>" onChange={() => {}} pluginProps={{}} disabled />);
57
-
58
- await waitFor(() => {
59
- expect(prosemirror(container).getAttribute('contenteditable')).toBe('false');
60
- });
61
-
62
- expect(prosemirror(container).getAttribute('role')).toBe('textbox');
63
- expect(prosemirror(container).getAttribute('data-pie-editor')).toBe('true');
64
- });
65
-
66
- // Online Testing queries [data-pie-editor][contenteditable="true"] to attach its answer-save
67
- // listener, so a read-only render has to carry the hook but not match that selector.
68
- it('marks a read-only editor as not editable so the hook can be filtered on it', async () => {
69
- const { container } = renderEditor({ disabled: true });
70
-
71
- await waitForEditor(container);
72
-
73
- expect(prosemirror(container).getAttribute('data-pie-editor')).toBe('true');
74
- expect(prosemirror(container).getAttribute('contenteditable')).toBe('false');
75
- expect(container.querySelector('[data-pie-editor][contenteditable="true"]')).toBeNull();
76
- });
77
- });
@@ -1,63 +0,0 @@
1
- import React from 'react';
2
- import { render, waitFor } from '@testing-library/react';
3
- import { EditableHtml } from '../components/EditableHtml';
4
-
5
- const renderEditor = (props) =>
6
- render(<EditableHtml markup="<p>teh</p>" onChange={() => {}} pluginProps={{}} {...props} />);
7
-
8
- const prosemirror = (container) => container.querySelector('.ProseMirror');
9
-
10
- const waitForEditor = async (container) => {
11
- await waitFor(() => {
12
- expect(prosemirror(container)).toBeInTheDocument();
13
- });
14
- };
15
-
16
- describe('spellCheck', () => {
17
- it('turns off browser spellcheck on the contenteditable when spellCheck is false', async () => {
18
- const { container } = renderEditor({ spellCheck: false });
19
-
20
- await waitForEditor(container);
21
-
22
- expect(prosemirror(container).getAttribute('spellcheck')).toBe('false');
23
- expect(prosemirror(container).getAttribute('autocorrect')).toBe('off');
24
- expect(prosemirror(container).getAttribute('autocapitalize')).toBe('off');
25
- });
26
-
27
- it('leaves browser spellcheck on when spellCheck is true', async () => {
28
- const { container } = renderEditor({ spellCheck: true });
29
-
30
- await waitForEditor(container);
31
-
32
- expect(prosemirror(container).getAttribute('spellcheck')).toBe('true');
33
- });
34
-
35
- it('keeps the browser default when spellCheck is not provided', async () => {
36
- const { container } = renderEditor();
37
-
38
- await waitForEditor(container);
39
-
40
- expect(prosemirror(container).getAttribute('spellcheck')).toBe('true');
41
- });
42
-
43
- it('updates the contenteditable when spellCheck changes on an existing editor', async () => {
44
- const { container, rerender } = renderEditor({ spellCheck: true });
45
-
46
- await waitForEditor(container);
47
- expect(prosemirror(container).getAttribute('spellcheck')).toBe('true');
48
-
49
- rerender(<EditableHtml markup="<p>teh</p>" onChange={() => {}} pluginProps={{}} spellCheck={false} />);
50
-
51
- await waitFor(() => {
52
- expect(prosemirror(container).getAttribute('spellcheck')).toBe('false');
53
- });
54
- });
55
-
56
- it('keeps spellcheck off for a disabled (read-only) editor', async () => {
57
- const { container } = renderEditor({ spellCheck: false, disabled: true });
58
-
59
- await waitForEditor(container);
60
-
61
- expect(prosemirror(container).getAttribute('spellcheck')).toBe('false');
62
- });
63
- });