@contentful/field-editor-markdown 1.15.4-canary.1 → 2.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.
Files changed (36) hide show
  1. package/dist/cjs/MarkdownActions.spec.js +163 -0
  2. package/dist/cjs/MarkdownEditor.js +2 -2
  3. package/dist/cjs/components/HeadingSelector.js +9 -1
  4. package/dist/cjs/components/MarkdownBottomBar.js +3 -3
  5. package/dist/cjs/components/MarkdownConstraints.js +2 -2
  6. package/dist/cjs/components/MarkdownPreview.js +6 -6
  7. package/dist/cjs/components/MarkdownPreviewSkeleton.js +2 -2
  8. package/dist/cjs/components/MarkdownTabs.js +6 -6
  9. package/dist/cjs/components/MarkdownTextarea/MarkdownTextarea.js +6 -6
  10. package/dist/cjs/components/MarkdownToolbar.js +62 -32
  11. package/dist/cjs/components/MarkdownToolbar.spec.js +144 -0
  12. package/dist/cjs/components/icons.js +2 -2
  13. package/dist/cjs/dialogs/CheatsheetModalDialog.js +18 -18
  14. package/dist/cjs/dialogs/EmdebExternalContentDialog.js +4 -4
  15. package/dist/cjs/dialogs/SpecialCharacterModalDialog.js +8 -7
  16. package/dist/cjs/dialogs/ZenModeModalDialog.js +15 -15
  17. package/dist/esm/MarkdownActions.spec.js +159 -0
  18. package/dist/esm/MarkdownEditor.js +1 -1
  19. package/dist/esm/components/HeadingSelector.js +9 -1
  20. package/dist/esm/components/MarkdownBottomBar.js +1 -1
  21. package/dist/esm/components/MarkdownConstraints.js +1 -1
  22. package/dist/esm/components/MarkdownPreview.js +1 -1
  23. package/dist/esm/components/MarkdownPreviewSkeleton.js +1 -1
  24. package/dist/esm/components/MarkdownTabs.js +1 -1
  25. package/dist/esm/components/MarkdownTextarea/MarkdownTextarea.js +1 -1
  26. package/dist/esm/components/MarkdownToolbar.js +55 -25
  27. package/dist/esm/components/MarkdownToolbar.spec.js +94 -0
  28. package/dist/esm/components/icons.js +1 -1
  29. package/dist/esm/dialogs/CheatsheetModalDialog.js +1 -1
  30. package/dist/esm/dialogs/EmdebExternalContentDialog.js +1 -1
  31. package/dist/esm/dialogs/SpecialCharacterModalDialog.js +3 -2
  32. package/dist/esm/dialogs/ZenModeModalDialog.js +1 -1
  33. package/dist/types/MarkdownActions.spec.d.ts +1 -0
  34. package/dist/types/components/HeadingSelector.d.ts +4 -2
  35. package/dist/types/components/MarkdownToolbar.spec.d.ts +1 -0
  36. package/package.json +11 -10
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _InsertLinkModalDialog = require("./dialogs/InsertLinkModalDialog");
6
+ const _InsertTableModalDialog = require("./dialogs/InsertTableModalDialog");
7
+ const _SpecialCharacterModalDialog = require("./dialogs/SpecialCharacterModalDialog");
8
+ const _ZenModeModalDialog = require("./dialogs/ZenModeModalDialog");
9
+ const _MarkdownActions = require("./MarkdownActions");
10
+ jest.mock('./dialogs/InsertLinkModalDialog', ()=>({
11
+ openInsertLinkDialog: jest.fn()
12
+ }));
13
+ jest.mock('./dialogs/SpecialCharacterModalDialog', ()=>({
14
+ openInsertSpecialCharacter: jest.fn()
15
+ }));
16
+ jest.mock('./dialogs/InsertTableModalDialog', ()=>({
17
+ openInsertTableDialog: jest.fn()
18
+ }));
19
+ jest.mock('./dialogs/ZenModeModalDialog', ()=>({
20
+ openZenMode: jest.fn()
21
+ }));
22
+ const mockedOpenInsertLinkDialog = _InsertLinkModalDialog.openInsertLinkDialog;
23
+ const mockedOpenInsertSpecialCharacter = _SpecialCharacterModalDialog.openInsertSpecialCharacter;
24
+ const mockedOpenInsertTableDialog = _InsertTableModalDialog.openInsertTableDialog;
25
+ const mockedOpenZenMode = _ZenModeModalDialog.openZenMode;
26
+ const createEditor = ()=>({
27
+ actions: {
28
+ h1: jest.fn(),
29
+ h2: jest.fn(),
30
+ h3: jest.fn(),
31
+ bold: jest.fn(),
32
+ italic: jest.fn(),
33
+ quote: jest.fn(),
34
+ ol: jest.fn(),
35
+ ul: jest.fn(),
36
+ strike: jest.fn(),
37
+ code: jest.fn(),
38
+ hr: jest.fn(),
39
+ indent: jest.fn(),
40
+ dedent: jest.fn(),
41
+ undo: jest.fn(),
42
+ redo: jest.fn(),
43
+ link: jest.fn(),
44
+ table: jest.fn()
45
+ },
46
+ usePrimarySelection: jest.fn(),
47
+ getSelectedText: jest.fn(),
48
+ insert: jest.fn(),
49
+ getContent: jest.fn(),
50
+ setContent: jest.fn(),
51
+ setCursor: jest.fn(),
52
+ focus: jest.fn()
53
+ });
54
+ const createSdk = ()=>({
55
+ dialogs: {},
56
+ locales: {
57
+ default: 'en-US',
58
+ fallbacks: {}
59
+ },
60
+ notifier: {
61
+ success: jest.fn()
62
+ }
63
+ });
64
+ describe('createMarkdownActions', ()=>{
65
+ beforeEach(()=>{
66
+ jest.clearAllMocks();
67
+ });
68
+ it('dispatches toolbar actions to the editor', ()=>{
69
+ const editor = createEditor();
70
+ const actions = (0, _MarkdownActions.createMarkdownActions)({
71
+ sdk: createSdk(),
72
+ editor: editor,
73
+ locale: 'en-US'
74
+ });
75
+ actions.headings.h2();
76
+ actions.simple.bold();
77
+ actions.simple.ul();
78
+ actions.history.undo();
79
+ expect(editor.actions.h2).toHaveBeenCalledTimes(1);
80
+ expect(editor.actions.bold).toHaveBeenCalledTimes(1);
81
+ expect(editor.actions.ul).toHaveBeenCalledTimes(1);
82
+ expect(editor.actions.undo).toHaveBeenCalledTimes(1);
83
+ });
84
+ it('opens the link dialog with the selected text and inserts a titled link', async ()=>{
85
+ const editor = createEditor();
86
+ const sdk = createSdk();
87
+ editor.getSelectedText.mockReturnValue('Contentful');
88
+ mockedOpenInsertLinkDialog.mockResolvedValue({
89
+ url: 'https://contentful.com',
90
+ text: 'ignored',
91
+ title: 'The best headless CMS'
92
+ });
93
+ const actions = (0, _MarkdownActions.createMarkdownActions)({
94
+ sdk,
95
+ editor: editor,
96
+ locale: 'en-US'
97
+ });
98
+ await actions.insertLink();
99
+ expect(editor.usePrimarySelection).toHaveBeenCalledTimes(1);
100
+ expect(mockedOpenInsertLinkDialog).toHaveBeenCalledWith(sdk.dialogs, {
101
+ selectedText: 'Contentful'
102
+ });
103
+ expect(editor.actions.link).toHaveBeenCalledWith('https://contentful.com', 'Contentful', 'The best headless CMS');
104
+ });
105
+ it('falls back to dialog text when no editor selection exists', async ()=>{
106
+ const editor = createEditor();
107
+ editor.getSelectedText.mockReturnValue('');
108
+ mockedOpenInsertLinkDialog.mockResolvedValue({
109
+ url: 'https://contentful.com',
110
+ text: 'Contentful',
111
+ title: ''
112
+ });
113
+ const actions = (0, _MarkdownActions.createMarkdownActions)({
114
+ sdk: createSdk(),
115
+ editor: editor,
116
+ locale: 'en-US'
117
+ });
118
+ await actions.insertLink();
119
+ expect(editor.actions.link).toHaveBeenCalledWith('https://contentful.com', 'Contentful', '');
120
+ });
121
+ it('inserts special characters and tables from dialog results', async ()=>{
122
+ const editor = createEditor();
123
+ mockedOpenInsertSpecialCharacter.mockResolvedValue('€');
124
+ mockedOpenInsertTableDialog.mockResolvedValue({
125
+ rows: 2,
126
+ cols: 3
127
+ });
128
+ const actions = (0, _MarkdownActions.createMarkdownActions)({
129
+ sdk: createSdk(),
130
+ editor: editor,
131
+ locale: 'en-US'
132
+ });
133
+ await actions.insertSpecialCharacter();
134
+ await actions.insertTable();
135
+ expect(editor.insert).toHaveBeenCalledWith('€');
136
+ expect(editor.actions.table).toHaveBeenCalledWith({
137
+ rows: 2,
138
+ cols: 3
139
+ });
140
+ });
141
+ it('updates content and restores cursor when zen mode closes', async ()=>{
142
+ const editor = createEditor();
143
+ mockedOpenZenMode.mockResolvedValue({
144
+ value: 'updated markdown',
145
+ cursor: {
146
+ line: 2,
147
+ ch: 4
148
+ }
149
+ });
150
+ const actions = (0, _MarkdownActions.createMarkdownActions)({
151
+ sdk: createSdk(),
152
+ editor: editor,
153
+ locale: 'en-US'
154
+ });
155
+ await actions.openZenMode();
156
+ expect(editor.setContent).toHaveBeenCalledWith('updated markdown');
157
+ expect(editor.setCursor).toHaveBeenCalledWith({
158
+ line: 2,
159
+ ch: 4
160
+ });
161
+ expect(editor.focus).toHaveBeenCalledTimes(1);
162
+ });
163
+ });
@@ -19,7 +19,7 @@ _export(exports, {
19
19
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
20
20
  const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
21
21
  const _fieldeditorshared = require("@contentful/field-editor-shared");
22
- const _emotion = require("emotion");
22
+ const _css = require("@emotion/css");
23
23
  const _MarkdownBottomBar = require("./components/MarkdownBottomBar");
24
24
  const _MarkdownConstraints = require("./components/MarkdownConstraints");
25
25
  const _MarkdownPreviewSkeleton = /*#__PURE__*/ _interop_require_default(require("./components/MarkdownPreviewSkeleton"));
@@ -76,7 +76,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
76
76
  }
77
77
  const MarkdownPreview = /*#__PURE__*/ _react.lazy(()=>Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./components/MarkdownPreview"))));
78
78
  const styles = {
79
- container: (0, _emotion.css)({
79
+ container: (0, _css.css)({
80
80
  display: 'flex',
81
81
  flexDirection: 'column',
82
82
  fontFamily: _f36tokens.default.fontStackPrimary
@@ -52,10 +52,18 @@ function _interop_require_wildcard(obj, nodeInterop) {
52
52
  return newObj;
53
53
  }
54
54
  const HeadingSelector = (props)=>{
55
+ const [isOpen, setIsOpen] = _react.useState(false);
55
56
  const handleMenuClick = (heading)=>{
57
+ setIsOpen(false);
56
58
  props.onSelect(heading);
57
59
  };
58
- return /*#__PURE__*/ _react.createElement(_f36components.Menu, null, /*#__PURE__*/ _react.createElement(_f36components.Menu.Trigger, null, props.children), /*#__PURE__*/ _react.createElement(_f36components.Menu.List, null, /*#__PURE__*/ _react.createElement(_f36components.Menu.Item, {
60
+ return /*#__PURE__*/ _react.createElement(_f36components.Menu, {
61
+ isOpen: isOpen,
62
+ onClose: ()=>setIsOpen(false)
63
+ }, /*#__PURE__*/ _react.createElement(_f36components.Menu.Trigger, null, props.renderTrigger({
64
+ isOpen,
65
+ onClick: ()=>setIsOpen((current)=>!current)
66
+ })), /*#__PURE__*/ _react.createElement(_f36components.Menu.List, null, /*#__PURE__*/ _react.createElement(_f36components.Menu.Item, {
59
67
  testId: "markdown-action-button-heading-h1",
60
68
  onClick: ()=>handleMenuClick('h1')
61
69
  }, "Heading 1"), /*#__PURE__*/ _react.createElement(_f36components.Menu.Item, {
@@ -22,7 +22,7 @@ _export(exports, {
22
22
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
23
23
  const _f36components = require("@contentful/f36-components");
24
24
  const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
25
- const _emotion = require("emotion");
25
+ const _css = require("@emotion/css");
26
26
  function _interop_require_default(obj) {
27
27
  return obj && obj.__esModule ? obj : {
28
28
  default: obj
@@ -71,7 +71,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
71
71
  }
72
72
  const SANITIZE_LINK = 'https://en.wikipedia.org/wiki/HTML_sanitization';
73
73
  const styles = {
74
- root: (0, _emotion.css)({
74
+ root: (0, _css.css)({
75
75
  display: 'flex',
76
76
  justifyContent: 'space-between',
77
77
  background: _f36tokens.default.gray100,
@@ -80,7 +80,7 @@ const styles = {
80
80
  borderBottomRightRadius: _f36tokens.default.borderRadiusSmall,
81
81
  padding: `${_f36tokens.default.spacingXs} ${_f36tokens.default.spacingS}`
82
82
  }),
83
- help: (0, _emotion.css)({
83
+ help: (0, _css.css)({
84
84
  color: _f36tokens.default.gray700,
85
85
  fontSize: _f36tokens.default.fontSizeS,
86
86
  '& button, & a': {
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "MarkdownConstraints", {
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
13
13
  const _fieldeditorshared = require("@contentful/field-editor-shared");
14
- const _emotion = require("emotion");
14
+ const _css = require("@emotion/css");
15
15
  function _interop_require_default(obj) {
16
16
  return obj && obj.__esModule ? obj : {
17
17
  default: obj
@@ -59,7 +59,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
59
59
  return newObj;
60
60
  }
61
61
  const styles = {
62
- root: (0, _emotion.css)({
62
+ root: (0, _css.css)({
63
63
  display: 'flex',
64
64
  justifyContent: 'space-between',
65
65
  fontSize: _f36tokens.default.fontSizeM,
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "default", {
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _reactmarkdown = /*#__PURE__*/ _interop_require_default(require("react-markdown"));
13
13
  const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
14
- const _emotion = require("emotion");
14
+ const _css = require("@emotion/css");
15
15
  const _rehyperaw = /*#__PURE__*/ _interop_require_default(require("rehype-raw"));
16
16
  const _rehypesanitize = /*#__PURE__*/ _interop_require_default(require("rehype-sanitize"));
17
17
  const _remarkgfm = /*#__PURE__*/ _interop_require_default(require("remark-gfm"));
@@ -63,7 +63,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
63
63
  return newObj;
64
64
  }
65
65
  const styles = {
66
- root: (0, _emotion.css)`
66
+ root: (0, _css.css)`
67
67
  border: 1px solid ${_f36tokens.default.gray400};
68
68
  border-width: 0 1px;
69
69
  word-wrap: break-word;
@@ -198,17 +198,17 @@ const styles = {
198
198
  display: block;
199
199
  }
200
200
  `,
201
- framed: (0, _emotion.css)({
201
+ framed: (0, _css.css)({
202
202
  height: '100%',
203
203
  maxHeight: '500px',
204
204
  overflowY: 'auto'
205
205
  }),
206
- zen: (0, _emotion.css)({
206
+ zen: (0, _css.css)({
207
207
  maxWidth: '650px',
208
208
  margin: '0 auto',
209
209
  border: 'none !important'
210
210
  }),
211
- rtl: (0, _emotion.css)({
211
+ rtl: (0, _css.css)({
212
212
  direction: 'rtl'
213
213
  })
214
214
  };
@@ -226,7 +226,7 @@ function MarkdownLink(props) {
226
226
  }, children);
227
227
  }
228
228
  const MarkdownPreview = /*#__PURE__*/ _react.memo((props)=>{
229
- const className = (0, _emotion.cx)(props.minHeight !== undefined ? (0, _emotion.css)({
229
+ const className = (0, _css.cx)(props.minHeight !== undefined ? (0, _css.css)({
230
230
  minHeight: props.minHeight
231
231
  }) : undefined, props.mode === 'default' ? styles.framed : styles.zen, props.direction === 'rtl' ? styles.rtl : undefined);
232
232
  return /*#__PURE__*/ _react.createElement("div", {
@@ -11,14 +11,14 @@ Object.defineProperty(exports, "default", {
11
11
  const _react = /*#__PURE__*/ _interop_require_default(require("react"));
12
12
  const _f36components = require("@contentful/f36-components");
13
13
  const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
14
- const _emotion = require("emotion");
14
+ const _css = require("@emotion/css");
15
15
  function _interop_require_default(obj) {
16
16
  return obj && obj.__esModule ? obj : {
17
17
  default: obj
18
18
  };
19
19
  }
20
20
  const styles = {
21
- root: (0, _emotion.css)({
21
+ root: (0, _css.css)({
22
22
  border: `1px solid ${_f36tokens.default.gray400}`,
23
23
  borderWidth: '0 1px',
24
24
  minHeight: '300px',
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "MarkdownTabs", {
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
13
- const _emotion = require("emotion");
13
+ const _css = require("@emotion/css");
14
14
  function _interop_require_default(obj) {
15
15
  return obj && obj.__esModule ? obj : {
16
16
  default: obj
@@ -58,7 +58,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
58
58
  return newObj;
59
59
  }
60
60
  const styles = {
61
- root: (0, _emotion.css)({
61
+ root: (0, _css.css)({
62
62
  display: 'flex',
63
63
  zIndex: 10,
64
64
  flexDirection: 'row',
@@ -67,7 +67,7 @@ const styles = {
67
67
  marginBottom: '-1px',
68
68
  fontSize: _f36tokens.default.fontSizeM
69
69
  }),
70
- tab: (0, _emotion.css)({
70
+ tab: (0, _css.css)({
71
71
  cursor: 'pointer',
72
72
  color: _f36tokens.default.gray700,
73
73
  padding: _f36tokens.default.spacingXs,
@@ -85,14 +85,14 @@ const styles = {
85
85
  },
86
86
  transition: `all ${_f36tokens.default.transitionEasingDefault} ${_f36tokens.default.transitionDurationShort}`
87
87
  }),
88
- inactiveTab: (0, _emotion.css)({
88
+ inactiveTab: (0, _css.css)({
89
89
  background: _f36tokens.default.gray200,
90
90
  borderBottomColor: _f36tokens.default.gray400,
91
91
  '&:hover': {
92
92
  background: _f36tokens.default.gray300
93
93
  }
94
94
  }),
95
- disabledTab: (0, _emotion.css)({
95
+ disabledTab: (0, _css.css)({
96
96
  cursor: 'not-allowed',
97
97
  '&:hover': {
98
98
  background: _f36tokens.default.gray200,
@@ -102,7 +102,7 @@ const styles = {
102
102
  };
103
103
  function MarkdownTabItem(props) {
104
104
  return /*#__PURE__*/ _react.createElement("div", {
105
- className: (0, _emotion.cx)(styles.tab, {
105
+ className: (0, _css.cx)(styles.tab, {
106
106
  [styles.inactiveTab]: props.isActive === false,
107
107
  [styles.disabledTab]: props.isDisabled === true
108
108
  }),
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "MarkdownTextarea", {
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
13
- const _emotion = require("emotion");
13
+ const _css = require("@emotion/css");
14
14
  const _createMarkdownEditor = require("./createMarkdownEditor");
15
15
  function _interop_require_default(obj) {
16
16
  return obj && obj.__esModule ? obj : {
@@ -59,7 +59,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
59
59
  return newObj;
60
60
  }
61
61
  const styles = {
62
- root: (0, _emotion.css)`
62
+ root: (0, _css.css)`
63
63
  border: 1px solid ${_f36tokens.default.gray400};
64
64
  border-width: 0 1px;
65
65
  overflow-y: auto;
@@ -127,19 +127,19 @@ const styles = {
127
127
  text-decoration: underline;
128
128
  }
129
129
  `,
130
- framed: (0, _emotion.css)({
130
+ framed: (0, _css.css)({
131
131
  '.CodeMirror': {
132
132
  maxHeight: '500px'
133
133
  }
134
134
  }),
135
- zen: (0, _emotion.css)({
135
+ zen: (0, _css.css)({
136
136
  border: 'none !important',
137
137
  '.CodeMirror-lines': {
138
138
  maxWidth: '650px',
139
139
  margin: '0 auto'
140
140
  }
141
141
  }),
142
- disabled: (0, _emotion.css)`
142
+ disabled: (0, _css.css)`
143
143
  .CodeMirror {
144
144
  background: ${_f36tokens.default.gray100};
145
145
  cursor: 'not-allowed';
@@ -177,7 +177,7 @@ const MarkdownTextarea = /*#__PURE__*/ _react.default.memo((props)=>{
177
177
  }, [
178
178
  editor
179
179
  ]);
180
- const className = (0, _emotion.cx)(styles.root, props.minHeight !== undefined ? (0, _emotion.css)({
180
+ const className = (0, _css.cx)(styles.root, props.minHeight !== undefined ? (0, _css.css)({
181
181
  minHeight: props.minHeight
182
182
  }) : undefined, props.mode === 'default' ? styles.framed : styles.zen, props.disabled && styles.disabled);
183
183
  return /*#__PURE__*/ _react.default.createElement("div", {
@@ -23,7 +23,7 @@ const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
23
23
  const _f36components = require("@contentful/f36-components");
24
24
  const _f36icons = require("@contentful/f36-icons");
25
25
  const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
26
- const _emotion = require("emotion");
26
+ const _css = require("@emotion/css");
27
27
  const _HeadingSelector = require("./HeadingSelector");
28
28
  const _icons = /*#__PURE__*/ _interop_require_wildcard(require("./icons"));
29
29
  const _InsertLinkSelector = require("./InsertLinkSelector");
@@ -74,7 +74,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
74
74
  return newObj;
75
75
  }
76
76
  const styles = {
77
- root: (0, _emotion.css)({
77
+ root: (0, _css.css)({
78
78
  position: 'relative',
79
79
  zIndex: Number(_f36tokens.default.zIndexWorkbenchHeader),
80
80
  border: `1px solid ${_f36tokens.default.gray400}`,
@@ -83,44 +83,69 @@ const styles = {
83
83
  borderTopLeftRadius: _f36tokens.default.borderRadiusSmall,
84
84
  overflow: 'hidden'
85
85
  }),
86
- button: (0, _emotion.css)({
86
+ button: (0, _css.css)({
87
87
  height: '30px',
88
88
  width: '36px',
89
89
  marginLeft: _f36tokens.default.spacing2Xs,
90
90
  marginRight: _f36tokens.default.spacing2Xs
91
91
  }),
92
- icon: (0, _emotion.css)({
92
+ icon: (0, _css.css)({
93
93
  fill: _f36tokens.default.gray700,
94
94
  verticalAlign: 'middle'
95
95
  }),
96
- zenButton: (0, _emotion.css)({
96
+ zenButton: (0, _css.css)({
97
97
  marginLeft: _f36tokens.default.spacingXs
98
98
  }),
99
- zenButtonPressed: (0, _emotion.css)({
99
+ zenButtonPressed: (0, _css.css)({
100
100
  backgroundColor: _f36tokens.default.gray400
101
101
  }),
102
- tooltip: (0, _emotion.css)({
103
- zIndex: Number(_f36tokens.default.zIndexTooltip)
102
+ tooltip: (0, _css.css)({
103
+ zIndex: Number(_f36tokens.default.zIndexTooltip),
104
+ pointerEvents: 'none'
104
105
  })
105
106
  };
106
107
  const ToolbarButton = /*#__PURE__*/ _react.forwardRef((props, ref)=>{
107
108
  const { tooltip, onClick, children, className, variant = 'transparent', tooltipPlace = 'top', isDisabled = false, ...otherProps } = props;
108
- return /*#__PURE__*/ _react.createElement(_f36components.Tooltip, {
109
- className: styles.tooltip,
110
- usePortal: true,
111
- placement: tooltipPlace,
112
- content: tooltip
113
- }, /*#__PURE__*/ _react.createElement(_f36components.IconButton, {
109
+ const pointerTriggeredRef = _react.useRef(false);
110
+ const handlePointerDown = _react.useCallback((event)=>{
111
+ if (isDisabled || !onClick || event.button !== 0) {
112
+ return;
113
+ }
114
+ event.preventDefault();
115
+ pointerTriggeredRef.current = true;
116
+ onClick(event);
117
+ }, [
118
+ isDisabled,
119
+ onClick
120
+ ]);
121
+ const handleClick = _react.useCallback((event)=>{
122
+ if (pointerTriggeredRef.current) {
123
+ pointerTriggeredRef.current = false;
124
+ return;
125
+ }
126
+ onClick?.(event);
127
+ }, [
128
+ onClick
129
+ ]);
130
+ return /*#__PURE__*/ _react.createElement(_f36components.IconButton, {
114
131
  ...otherProps,
115
132
  ref: ref,
116
- className: (0, _emotion.cx)(styles.button, className),
133
+ className: (0, _css.cx)(styles.button, className),
117
134
  isDisabled: isDisabled,
118
- onClick: onClick,
135
+ onMouseDown: handlePointerDown,
136
+ onClick: handleClick,
119
137
  variant: variant,
120
138
  size: "small",
121
139
  icon: children,
122
- "aria-label": tooltip
123
- }));
140
+ "aria-label": tooltip,
141
+ withTooltip: true,
142
+ tooltipProps: {
143
+ className: styles.tooltip,
144
+ usePortal: true,
145
+ placement: tooltipPlace,
146
+ content: tooltip
147
+ }
148
+ });
124
149
  });
125
150
  ToolbarButton.displayName = 'ToolbarButton';
126
151
  function MainButtons(props) {
@@ -130,16 +155,19 @@ function MainButtons(props) {
130
155
  if (heading && props.actions.headings[heading]) {
131
156
  props.actions.headings[heading]();
132
157
  }
133
- }
134
- }, /*#__PURE__*/ _react.createElement(ToolbarButton, {
135
- isDisabled: props.disabled,
136
- testId: "markdown-action-button-heading",
137
- tooltip: "Headings",
138
- tooltipPlace: tooltipPlace
139
- }, /*#__PURE__*/ _react.createElement(_f36icons.TextHIcon, {
140
- "aria-label": "Headings",
141
- className: styles.icon
142
- }))), /*#__PURE__*/ _react.createElement(ToolbarButton, {
158
+ },
159
+ renderTrigger: ({ isOpen, onClick })=>/*#__PURE__*/ _react.createElement(ToolbarButton, {
160
+ isDisabled: props.disabled,
161
+ testId: "markdown-action-button-heading",
162
+ tooltip: "Headings",
163
+ tooltipPlace: tooltipPlace,
164
+ onClick: onClick,
165
+ "aria-expanded": isOpen
166
+ }, /*#__PURE__*/ _react.createElement(_f36icons.TextHIcon, {
167
+ "aria-label": "Headings",
168
+ className: styles.icon
169
+ }))
170
+ }), /*#__PURE__*/ _react.createElement(ToolbarButton, {
143
171
  isDisabled: props.disabled,
144
172
  testId: "markdown-action-button-bold",
145
173
  tooltip: "Bold",
@@ -300,6 +328,9 @@ function AdditionalButtons(props) {
300
328
  }
301
329
  function DefaultMarkdownToolbar(props) {
302
330
  const [showAdditional, setShowAdditional] = _react.useState(false);
331
+ const toggleAdditionalActions = _react.useCallback(()=>{
332
+ setShowAdditional((current)=>!current);
333
+ }, []);
303
334
  return /*#__PURE__*/ _react.createElement("div", {
304
335
  className: styles.root
305
336
  }, /*#__PURE__*/ _react.createElement(_f36components.Flex, {
@@ -311,9 +342,8 @@ function DefaultMarkdownToolbar(props) {
311
342
  isDisabled: props.disabled,
312
343
  testId: "markdown-action-button-toggle-additional",
313
344
  tooltip: showAdditional ? 'Hide additional actions' : 'More actions',
314
- onClick: ()=>{
315
- setShowAdditional(!showAdditional);
316
- }
345
+ "aria-expanded": showAdditional,
346
+ onClick: toggleAdditionalActions
317
347
  }, /*#__PURE__*/ _react.createElement(_f36icons.DotsThreeIcon, {
318
348
  className: styles.icon
319
349
  }))), /*#__PURE__*/ _react.createElement(_f36components.Flex, null, /*#__PURE__*/ _react.createElement(_InsertLinkSelector.InsertLinkSelector, {
@@ -353,7 +383,7 @@ function ZenMarkdownToolbar(props) {
353
383
  testId: "markdown-action-button-zen-close",
354
384
  variant: "secondary",
355
385
  size: "small",
356
- className: (0, _emotion.cx)(styles.zenButton, styles.zenButtonPressed),
386
+ className: (0, _css.cx)(styles.zenButton, styles.zenButtonPressed),
357
387
  onClick: ()=>{
358
388
  props.actions.closeZenMode();
359
389
  },