@bendyline/squisq-editor-react 1.2.2 → 1.4.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 (106) hide show
  1. package/dist/EditorContext.d.ts +65 -1
  2. package/dist/EditorContext.d.ts.map +1 -1
  3. package/dist/EditorContext.js +31 -4
  4. package/dist/EditorContext.js.map +1 -1
  5. package/dist/EditorShell.d.ts +112 -2
  6. package/dist/EditorShell.d.ts.map +1 -1
  7. package/dist/EditorShell.js +95 -11
  8. package/dist/EditorShell.js.map +1 -1
  9. package/dist/ImageNodeView.d.ts.map +1 -1
  10. package/dist/ImageNodeView.js +12 -2
  11. package/dist/ImageNodeView.js.map +1 -1
  12. package/dist/MediaBin.d.ts +12 -1
  13. package/dist/MediaBin.d.ts.map +1 -1
  14. package/dist/MediaBin.js +29 -4
  15. package/dist/MediaBin.js.map +1 -1
  16. package/dist/MentionExtension.d.ts +22 -0
  17. package/dist/MentionExtension.d.ts.map +1 -0
  18. package/dist/MentionExtension.js +242 -0
  19. package/dist/MentionExtension.js.map +1 -0
  20. package/dist/RawEditor.d.ts +8 -1
  21. package/dist/RawEditor.d.ts.map +1 -1
  22. package/dist/RawEditor.js +167 -30
  23. package/dist/RawEditor.js.map +1 -1
  24. package/dist/TemplateAnnotation.d.ts.map +1 -1
  25. package/dist/TemplateAnnotation.js +4 -2
  26. package/dist/TemplateAnnotation.js.map +1 -1
  27. package/dist/Toolbar.d.ts +7 -1
  28. package/dist/Toolbar.d.ts.map +1 -1
  29. package/dist/Toolbar.js +57 -18
  30. package/dist/Toolbar.js.map +1 -1
  31. package/dist/Tooltip.d.ts +10 -0
  32. package/dist/Tooltip.d.ts.map +1 -0
  33. package/dist/Tooltip.js +104 -0
  34. package/dist/Tooltip.js.map +1 -0
  35. package/dist/ViewSwitcher.d.ts +1 -1
  36. package/dist/ViewSwitcher.d.ts.map +1 -1
  37. package/dist/ViewSwitcher.js +10 -4
  38. package/dist/ViewSwitcher.js.map +1 -1
  39. package/dist/WysiwygEditor.d.ts +13 -2
  40. package/dist/WysiwygEditor.d.ts.map +1 -1
  41. package/dist/WysiwygEditor.js +239 -4
  42. package/dist/WysiwygEditor.js.map +1 -1
  43. package/dist/__tests__/detectMarkdown.test.d.ts +2 -0
  44. package/dist/__tests__/detectMarkdown.test.d.ts.map +1 -0
  45. package/dist/__tests__/detectMarkdown.test.js +69 -0
  46. package/dist/__tests__/detectMarkdown.test.js.map +1 -0
  47. package/dist/__tests__/fileKind.test.d.ts +2 -0
  48. package/dist/__tests__/fileKind.test.d.ts.map +1 -0
  49. package/dist/__tests__/fileKind.test.js +81 -0
  50. package/dist/__tests__/fileKind.test.js.map +1 -0
  51. package/dist/__tests__/mediaAttachmentFlow.test.d.ts +2 -0
  52. package/dist/__tests__/mediaAttachmentFlow.test.d.ts.map +1 -0
  53. package/dist/__tests__/mediaAttachmentFlow.test.js +99 -0
  54. package/dist/__tests__/mediaAttachmentFlow.test.js.map +1 -0
  55. package/dist/__tests__/tiptapBridge.test.js +49 -0
  56. package/dist/__tests__/tiptapBridge.test.js.map +1 -1
  57. package/dist/__tests__/tiptapImageRoundTrip.test.d.ts +2 -0
  58. package/dist/__tests__/tiptapImageRoundTrip.test.d.ts.map +1 -0
  59. package/dist/__tests__/tiptapImageRoundTrip.test.js +68 -0
  60. package/dist/__tests__/tiptapImageRoundTrip.test.js.map +1 -0
  61. package/dist/detectMarkdown.d.ts +20 -0
  62. package/dist/detectMarkdown.d.ts.map +1 -0
  63. package/dist/detectMarkdown.js +61 -0
  64. package/dist/detectMarkdown.js.map +1 -0
  65. package/dist/fileKind.d.ts +30 -0
  66. package/dist/fileKind.d.ts.map +1 -0
  67. package/dist/fileKind.js +123 -0
  68. package/dist/fileKind.js.map +1 -0
  69. package/dist/hooks/useFileDrop.d.ts.map +1 -1
  70. package/dist/hooks/useFileDrop.js +9 -7
  71. package/dist/hooks/useFileDrop.js.map +1 -1
  72. package/dist/index.d.ts +4 -1
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +4 -0
  75. package/dist/index.js.map +1 -1
  76. package/dist/mediaDragMime.d.ts +17 -0
  77. package/dist/mediaDragMime.d.ts.map +1 -0
  78. package/dist/mediaDragMime.js +22 -0
  79. package/dist/mediaDragMime.js.map +1 -0
  80. package/dist/tiptapBridge.d.ts.map +1 -1
  81. package/dist/tiptapBridge.js +99 -6
  82. package/dist/tiptapBridge.js.map +1 -1
  83. package/package.json +9 -7
  84. package/src/EditorContext.tsx +106 -3
  85. package/src/EditorShell.tsx +313 -21
  86. package/src/ImageNodeView.tsx +15 -2
  87. package/src/MediaBin.tsx +45 -4
  88. package/src/MentionExtension.tsx +258 -0
  89. package/src/RawEditor.tsx +193 -37
  90. package/src/TemplateAnnotation.ts +4 -2
  91. package/src/Toolbar.tsx +111 -48
  92. package/src/Tooltip.tsx +124 -0
  93. package/src/ViewSwitcher.tsx +15 -5
  94. package/src/WysiwygEditor.tsx +270 -5
  95. package/src/__tests__/detectMarkdown.test.ts +88 -0
  96. package/src/__tests__/fileKind.test.ts +96 -0
  97. package/src/__tests__/mediaAttachmentFlow.test.ts +110 -0
  98. package/src/__tests__/tiptapBridge.test.ts +58 -0
  99. package/src/__tests__/tiptapImageRoundTrip.test.ts +73 -0
  100. package/src/detectMarkdown.ts +62 -0
  101. package/src/fileKind.ts +134 -0
  102. package/src/hooks/useFileDrop.ts +10 -6
  103. package/src/index.ts +11 -0
  104. package/src/mediaDragMime.ts +32 -0
  105. package/src/styles/editor.css +214 -8
  106. package/src/tiptapBridge.ts +107 -6
package/dist/RawEditor.js CHANGED
@@ -11,6 +11,7 @@ import Editor, { loader } from '@monaco-editor/react';
11
11
  import * as monaco from 'monaco-editor';
12
12
  import { useEditorContext } from './EditorContext';
13
13
  import { getAvailableTemplates } from '@bendyline/squisq/doc';
14
+ import { SQUISQ_MEDIA_MIME, parseSquisqMediaPayload } from './mediaDragMime';
14
15
  // Use locally installed monaco-editor instead of CDN.
15
16
  //
16
17
  // NOTE: By default this imports the full monaco-editor with all 80+ languages
@@ -26,51 +27,185 @@ loader.config({ monaco });
26
27
  * Raw markdown editor using Monaco Editor.
27
28
  * Binds to the shared EditorContext for source synchronization.
28
29
  */
29
- export function RawEditor({ theme = 'vs', minimap = false, fontSize = 14, wordWrap = 'on', className, }) {
30
- const { markdownSource, setMarkdownSource, setMonacoEditor } = useEditorContext();
30
+ export function RawEditor({ theme = 'vs', minimap = false, fontSize = 14, wordWrap = 'on', className, submitOnEnter, readOnly = false, }) {
31
+ const { markdownSource, setMarkdownSource, setMonacoEditor, language, mentionProvider } = useEditorContext();
31
32
  const editorRef = useRef(null);
32
33
  const isExternalUpdate = useRef(false);
33
34
  const completionDisposable = useRef(null);
35
+ const mentionCompletionDisposable = useRef(null);
36
+ const dropCleanupRef = useRef(null);
37
+ const keyDisposable = useRef(null);
38
+ // Ref so the keydown handler always sees the latest callback.
39
+ const submitOnEnterRef = useRef(submitOnEnter);
40
+ useEffect(() => {
41
+ submitOnEnterRef.current = submitOnEnter;
42
+ }, [submitOnEnter]);
43
+ // Ref so the completion provider — registered once at mount — always
44
+ // sees the latest mentionProvider without needing to unregister.
45
+ const mentionProviderRef = useRef(mentionProvider);
46
+ useEffect(() => {
47
+ mentionProviderRef.current = mentionProvider;
48
+ }, [mentionProvider]);
34
49
  const handleMount = useCallback((editor, monaco) => {
35
50
  editorRef.current = editor;
36
51
  setMonacoEditor(editor);
37
52
  editor.focus();
38
53
  // Dispose any previous completion provider (from a prior mount)
39
54
  completionDisposable.current?.dispose();
40
- // Register template annotation completion provider for {[ trigger
41
- const templates = getAvailableTemplates();
42
- completionDisposable.current = monaco.languages.registerCompletionItemProvider('markdown', {
43
- triggerCharacters: ['['],
44
- provideCompletionItems(model, position) {
45
- const lineContent = model.getLineContent(position.lineNumber);
46
- // Only trigger inside a heading line that has {[ before the cursor
47
- if (!/^#{1,6}\s/.test(lineContent))
48
- return { suggestions: [] };
49
- const textBeforeCursor = lineContent.substring(0, position.column - 1);
50
- const bracketIdx = textBeforeCursor.lastIndexOf('{[');
51
- if (bracketIdx === -1)
52
- return { suggestions: [] };
53
- // The range to replace: from after {[ to the cursor
54
- const startCol = bracketIdx + 3; // after {[
55
- const range = new monaco.Range(position.lineNumber, startCol, position.lineNumber, position.column);
56
- const suggestions = templates.map((name) => ({
57
- label: name,
58
- kind: monaco.languages.CompletionItemKind.Value,
59
- insertText: name + ']}',
60
- range,
61
- detail: 'Block template',
62
- sortText: name,
63
- }));
64
- return { suggestions };
65
- },
55
+ completionDisposable.current = null;
56
+ mentionCompletionDisposable.current?.dispose();
57
+ mentionCompletionDisposable.current = null;
58
+ // Register the `{[template]}` completion provider only for markdown
59
+ // files — it's meaningless for TypeScript, JSON, Python, etc.
60
+ if (language === 'markdown') {
61
+ const templates = getAvailableTemplates();
62
+ completionDisposable.current = monaco.languages.registerCompletionItemProvider('markdown', {
63
+ triggerCharacters: ['['],
64
+ provideCompletionItems(model, position) {
65
+ const lineContent = model.getLineContent(position.lineNumber);
66
+ // Only trigger inside a heading line that has {[ before the cursor
67
+ if (!/^#{1,6}\s/.test(lineContent))
68
+ return { suggestions: [] };
69
+ const textBeforeCursor = lineContent.substring(0, position.column - 1);
70
+ const bracketIdx = textBeforeCursor.lastIndexOf('{[');
71
+ if (bracketIdx === -1)
72
+ return { suggestions: [] };
73
+ // The range to replace: from after {[ to the cursor
74
+ const startCol = bracketIdx + 3; // after {[
75
+ const range = new monaco.Range(position.lineNumber, startCol, position.lineNumber, position.column);
76
+ const suggestions = templates.map((name) => ({
77
+ label: name,
78
+ kind: monaco.languages.CompletionItemKind.Value,
79
+ insertText: name + ']}',
80
+ range,
81
+ detail: 'Block template',
82
+ sortText: name,
83
+ }));
84
+ return { suggestions };
85
+ },
86
+ });
87
+ // `@mention` completion — queries the shared MentionProvider. Keep
88
+ // this in its own registration so we can dispose it independently
89
+ // of the template provider, and so the trigger character is just
90
+ // `@` (not `[`).
91
+ mentionCompletionDisposable.current = monaco.languages.registerCompletionItemProvider('markdown', {
92
+ triggerCharacters: ['@'],
93
+ async provideCompletionItems(model, position) {
94
+ const provider = mentionProviderRef.current;
95
+ if (!provider)
96
+ return { suggestions: [] };
97
+ const lineContent = model.getLineContent(position.lineNumber);
98
+ const textBeforeCursor = lineContent.substring(0, position.column - 1);
99
+ const atIdx = textBeforeCursor.lastIndexOf('@');
100
+ if (atIdx === -1)
101
+ return { suggestions: [] };
102
+ // `@` must be at line start or preceded by whitespace/punct —
103
+ // skip e.g. email addresses like `foo@bar`.
104
+ if (atIdx > 0) {
105
+ const prevChar = textBeforeCursor[atIdx - 1];
106
+ if (!/[\s\p{P}]/u.test(prevChar))
107
+ return { suggestions: [] };
108
+ }
109
+ const query = textBeforeCursor.slice(atIdx + 1);
110
+ // Only fire for short queries — once the user has typed
111
+ // a full word, the popover gets noisy.
112
+ if (query.length > 40)
113
+ return { suggestions: [] };
114
+ if (/\s/.test(query))
115
+ return { suggestions: [] };
116
+ let candidates;
117
+ try {
118
+ candidates = await provider(query);
119
+ }
120
+ catch {
121
+ return { suggestions: [] };
122
+ }
123
+ const range = new monaco.Range(position.lineNumber, atIdx + 1, position.lineNumber, position.column);
124
+ return {
125
+ suggestions: candidates.map((c) => ({
126
+ label: `@${c.label}`,
127
+ kind: monaco.languages.CompletionItemKind.User,
128
+ insertText: `@[${c.label}](${c.scheme}:${c.id}) `,
129
+ range,
130
+ ...(c.description ? { detail: c.description } : {}),
131
+ sortText: c.label,
132
+ })),
133
+ };
134
+ },
135
+ });
136
+ }
137
+ // Chat-composer mode: intercept Enter before Monaco inserts a newline.
138
+ // Cmd/Ctrl+Enter falls through so the native newline still works.
139
+ keyDisposable.current?.dispose();
140
+ keyDisposable.current = editor.onKeyDown((e) => {
141
+ if (e.keyCode !== monaco.KeyCode.Enter)
142
+ return;
143
+ if (!submitOnEnterRef.current)
144
+ return;
145
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
146
+ return;
147
+ e.preventDefault();
148
+ e.stopPropagation();
149
+ submitOnEnterRef.current();
66
150
  });
67
- }, [setMonacoEditor]);
151
+ // Attach native drop listeners for in-app MediaBin drags. Monaco's own
152
+ // drop handling doesn't know about our custom MIME type, so we insert
153
+ // markdown image syntax explicitly in the capture phase.
154
+ dropCleanupRef.current?.();
155
+ const domNode = editor.getDomNode();
156
+ if (domNode) {
157
+ const onDragOver = (e) => {
158
+ if (e.dataTransfer?.types.includes(SQUISQ_MEDIA_MIME)) {
159
+ e.preventDefault();
160
+ e.dataTransfer.dropEffect = 'copy';
161
+ }
162
+ };
163
+ const onDrop = (e) => {
164
+ const dt = e.dataTransfer;
165
+ if (!dt)
166
+ return;
167
+ const raw = dt.getData(SQUISQ_MEDIA_MIME);
168
+ if (!raw)
169
+ return;
170
+ const payload = parseSquisqMediaPayload(raw);
171
+ if (!payload || !payload.mimeType.startsWith('image/'))
172
+ return;
173
+ e.preventDefault();
174
+ e.stopPropagation();
175
+ const target = editor.getTargetAtClientPoint(e.clientX, e.clientY);
176
+ const position = target?.position ?? editor.getPosition();
177
+ if (!position)
178
+ return;
179
+ const markdown = `![${payload.alt}](${payload.name})`;
180
+ editor.executeEdits('squisq-media-drop', [
181
+ {
182
+ range: new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
183
+ text: markdown,
184
+ forceMoveMarkers: true,
185
+ },
186
+ ]);
187
+ editor.focus();
188
+ };
189
+ domNode.addEventListener('dragover', onDragOver, true);
190
+ domNode.addEventListener('drop', onDrop, true);
191
+ dropCleanupRef.current = () => {
192
+ domNode.removeEventListener('dragover', onDragOver, true);
193
+ domNode.removeEventListener('drop', onDrop, true);
194
+ };
195
+ }
196
+ }, [setMonacoEditor, language]);
68
197
  // Unregister on unmount
69
198
  useEffect(() => {
70
199
  return () => {
71
200
  setMonacoEditor(null);
72
201
  completionDisposable.current?.dispose();
73
202
  completionDisposable.current = null;
203
+ mentionCompletionDisposable.current?.dispose();
204
+ mentionCompletionDisposable.current = null;
205
+ dropCleanupRef.current?.();
206
+ dropCleanupRef.current = null;
207
+ keyDisposable.current?.dispose();
208
+ keyDisposable.current = null;
74
209
  };
75
210
  }, [setMonacoEditor]);
76
211
  const handleChange = useCallback((value) => {
@@ -92,7 +227,7 @@ export function RawEditor({ theme = 'vs', minimap = false, fontSize = 14, wordWr
92
227
  }
93
228
  }
94
229
  }, [markdownSource]);
95
- return (_jsx("div", { className: className, style: { width: '100%', height: '100%' }, "data-testid": "raw-editor", children: _jsx(Editor, { defaultLanguage: "markdown", value: markdownSource, theme: theme, onMount: handleMount, onChange: handleChange, options: {
230
+ return (_jsx("div", { className: className, style: { width: '100%', height: '100%' }, "data-testid": "raw-editor", children: _jsx(Editor, { defaultLanguage: language, value: markdownSource, theme: theme, onMount: handleMount, onChange: handleChange, options: {
96
231
  fontSize,
97
232
  wordWrap,
98
233
  minimap: { enabled: minimap },
@@ -104,6 +239,8 @@ export function RawEditor({ theme = 'vs', minimap = false, fontSize = 14, wordWr
104
239
  bracketPairColorization: { enabled: true },
105
240
  guides: { indentation: true },
106
241
  padding: { top: 12, bottom: 12 },
242
+ readOnly,
243
+ domReadOnly: readOnly,
107
244
  } }) }));
108
245
  }
109
246
  //# sourceMappingURL=RawEditor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RawEditor.js","sourceRoot":"","sources":["../src/RawEditor.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RawEditor.js","sourceRoot":"","sources":["../src/RawEditor.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateAnnotation.d.ts","sourceRoot":"","sources":["../src/TemplateAnnotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,sFAiD9B,CAAC"}
1
+ {"version":3,"file":"TemplateAnnotation.d.ts","sourceRoot":"","sources":["../src/TemplateAnnotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,sFAmD9B,CAAC"}
@@ -46,7 +46,10 @@ export const HeadingWithTemplate = Heading.extend({
46
46
  const tag = `h${level}`;
47
47
  const templateName = HTMLAttributes['data-template'];
48
48
  if (templateName) {
49
- // Render heading with a trailing badge span
49
+ // Render heading with a trailing badge span. The badge has no text
50
+ // content — its label is painted via CSS `content: attr(data-template)`
51
+ // so the template name never becomes part of the serialized heading
52
+ // text (which would leak into markdown on round-trip).
50
53
  return [
51
54
  tag,
52
55
  HTMLAttributes,
@@ -58,7 +61,6 @@ export const HeadingWithTemplate = Heading.extend({
58
61
  contenteditable: 'false',
59
62
  'data-template': templateName,
60
63
  },
61
- templateName,
62
64
  ],
63
65
  ];
64
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateAnnotation.js","sourceRoot":"","sources":["../src/TemplateAnnotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,OAAO,MAAM,2BAA2B,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAChD,aAAa;QACX,OAAO;YACL,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE;YAClB,YAAY,EAAE;gBACZ,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,CAAC,OAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,IAAI,IAAI;gBAClF,UAAU,EAAE,CAAC,UAAmC,EAAE,EAAE;oBAClD,IAAI,CAAC,UAAU,CAAC,YAAY;wBAAE,OAAO,EAAE,CAAC;oBACxC,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,YAAY,EAAE,CAAC;gBACtD,CAAC;aACF;YACD,kBAAkB,EAAE;gBAClB,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,CAAC,OAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,sBAAsB,CAAC,IAAI,IAAI;gBACzF,UAAU,EAAE,CAAC,UAAmC,EAAE,EAAE;oBAClD,IAAI,CAAC,UAAU,CAAC,kBAAkB;wBAAE,OAAO,EAAE,CAAC;oBAC9C,OAAO,EAAE,sBAAsB,EAAE,UAAU,CAAC,kBAAkB,EAAE,CAAC;gBACnE,CAAC;aACF;SACF,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,YAAY,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;QAErD,IAAI,YAAY,EAAE,CAAC;YACjB,4CAA4C;YAC5C,OAAO;gBACL,GAAG;gBACH,cAAc;gBACd,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,EAAE,CAAC,CAAC;gBAChD;oBACE,MAAM;oBACN;wBACE,KAAK,EAAE,uBAAuB;wBAC9B,eAAe,EAAE,OAAO;wBACxB,eAAe,EAAE,YAAY;qBAC9B;oBACD,YAAY;iBACb;aACF,CAAC;QACJ,CAAC;QAED,yCAAyC;QACzC,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"TemplateAnnotation.js","sourceRoot":"","sources":["../src/TemplateAnnotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,OAAO,MAAM,2BAA2B,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAChD,aAAa;QACX,OAAO;YACL,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE;YAClB,YAAY,EAAE;gBACZ,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,CAAC,OAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,IAAI,IAAI;gBAClF,UAAU,EAAE,CAAC,UAAmC,EAAE,EAAE;oBAClD,IAAI,CAAC,UAAU,CAAC,YAAY;wBAAE,OAAO,EAAE,CAAC;oBACxC,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,YAAY,EAAE,CAAC;gBACtD,CAAC;aACF;YACD,kBAAkB,EAAE;gBAClB,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,CAAC,OAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,sBAAsB,CAAC,IAAI,IAAI;gBACzF,UAAU,EAAE,CAAC,UAAmC,EAAE,EAAE;oBAClD,IAAI,CAAC,UAAU,CAAC,kBAAkB;wBAAE,OAAO,EAAE,CAAC;oBAC9C,OAAO,EAAE,sBAAsB,EAAE,UAAU,CAAC,kBAAkB,EAAE,CAAC;gBACnE,CAAC;aACF;SACF,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,YAAY,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;QAErD,IAAI,YAAY,EAAE,CAAC;YACjB,mEAAmE;YACnE,wEAAwE;YACxE,oEAAoE;YACpE,uDAAuD;YACvD,OAAO;gBACL,GAAG;gBACH,cAAc;gBACd,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,EAAE,CAAC,CAAC;gBAChD;oBACE,MAAM;oBACN;wBACE,KAAK,EAAE,uBAAuB;wBAC9B,eAAe,EAAE,OAAO;wBACxB,eAAe,EAAE,YAAY;qBAC9B;iBACF;aACF,CAAC;QACJ,CAAC;QAED,yCAAyC;QACzC,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;CACF,CAAC,CAAC"}
package/dist/Toolbar.d.ts CHANGED
@@ -20,11 +20,17 @@ export interface ToolbarProps {
20
20
  slotAfterActions?: ReactNode;
21
21
  /** Content rendered at the rightmost end of the toolbar, after all other elements. */
22
22
  slotRight?: ReactNode;
23
+ /**
24
+ * Whether to include the "Play" (preview) tab in the view switcher.
25
+ * Defaults to true. Hosts that don't want the slideshow preview — e.g.
26
+ * editing free-form prompts — can pass false to suppress it.
27
+ */
28
+ showPlayTab?: boolean;
23
29
  }
24
30
  /**
25
31
  * Formatting toolbar.
26
32
  * - WYSIWYG: calls Tiptap chain commands (toggleBold, etc.)
27
33
  * - Raw: appends markdown syntax to the source
28
34
  */
29
- export declare function Toolbar({ className, showFiles, onToggleFiles, slotLeft, slotAfterActions, slotRight, }: ToolbarProps): import("react/jsx-runtime").JSX.Element;
35
+ export declare function Toolbar({ className, showFiles, onToggleFiles, slotLeft, slotAfterActions, slotRight, showPlayTab, }: ToolbarProps): import("react/jsx-runtime").JSX.Element;
30
36
  //# sourceMappingURL=Toolbar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../src/Toolbar.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAevC,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sFAAsF;IACtF,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,sFAAsF;IACtF,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAyFD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,SAAS,EACT,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,SAAS,GACV,EAAE,YAAY,2CA8xBd"}
1
+ {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../src/Toolbar.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAevC,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sFAAsF;IACtF,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,sFAAsF;IACtF,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA8FD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,SAAS,EACT,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,SAAS,EACT,WAAkB,GACnB,EAAE,YAAY,2CAi1Bd"}
package/dist/Toolbar.js CHANGED
@@ -6,11 +6,11 @@ import { getAvailableTemplates } from '@bendyline/squisq/doc';
6
6
  const TEMPLATE_NAMES = getAvailableTemplates();
7
7
  const VIEWS = [
8
8
  { id: 'wysiwyg', label: 'Editor', shortcut: '⌘1' },
9
- { id: 'raw', label: 'Raw', shortcut: '⌘2' },
9
+ { id: 'raw', label: 'Markdown', shortLabel: 'MD', shortcut: '⌘2' },
10
10
  { id: 'preview', label: 'Play', shortcut: '⌘3' },
11
11
  ];
12
12
  const BUTTONS = [
13
- // Format group
13
+ // Format group — B/I/S trio.
14
14
  {
15
15
  id: 'bold',
16
16
  label: 'B',
@@ -35,20 +35,23 @@ const BUTTONS = [
35
35
  group: 'format',
36
36
  iconStyle: { textDecoration: 'line-through' },
37
37
  },
38
- { id: 'code', label: '<>', icon: '`', title: 'Inline code', group: 'format' },
38
+ // Lists group sits between format and structure so bullets/numbers
39
+ // are adjacent to the inline formatters people reach for together.
40
+ { id: 'ul', label: '•', icon: '•', title: 'Bullet list', group: 'lists' },
41
+ { id: 'ol', label: '1.', icon: '1.', title: 'Numbered list', group: 'lists' },
39
42
  // Structure group
40
43
  { id: 'h1', label: 'H1', icon: 'H1', title: 'Heading 1', group: 'structure' },
41
44
  { id: 'h2', label: 'H2', icon: 'H2', title: 'Heading 2', group: 'structure' },
42
45
  { id: 'h3', label: 'H3', icon: 'H3', title: 'Heading 3', group: 'structure' },
43
- { id: 'quote', label: '❝', icon: '❝', title: 'Blockquote', group: 'structure' },
44
- // Insert group
45
- { id: 'ul', label: '•', icon: '•', title: 'Bullet list', group: 'insert' },
46
- { id: 'ol', label: '1.', icon: '1.', title: 'Numbered list', group: 'insert' },
46
+ // Insert group block-level inserts (quote, code blocks, rules)
47
+ { id: 'quote', label: '❝', icon: '❝', title: 'Blockquote', group: 'insert' },
47
48
  { id: 'codeblock', label: '{ }', icon: '{ }', title: 'Code block', group: 'insert' },
49
+ { id: 'code', label: '</>', icon: '</>', title: 'Inline code', group: 'insert' },
48
50
  { id: 'hr', label: '—', icon: '—', title: 'Horizontal rule', group: 'insert' },
49
- { id: 'link', label: '🔗', icon: '🔗', title: 'Insert link', group: 'insert' },
50
- { id: 'table', label: 'table', icon: '', title: 'Insert table', group: 'insert' },
51
- { id: 'image', label: '🖼', icon: '🖼', title: 'Insert image', group: 'insert' },
51
+ // Media group links, tables, images
52
+ { id: 'link', label: '🔗', icon: '🔗', title: 'Insert link', group: 'media' },
53
+ { id: 'table', label: 'table', icon: '', title: 'Insert table', group: 'media' },
54
+ { id: 'image', label: '🖼', icon: '🖼', title: 'Insert image', group: 'media' },
52
55
  ];
53
56
  // ─── Tiptap active-state map ────────────────────────────
54
57
  /** Returns true if the given button id is currently active in Tiptap */
@@ -87,8 +90,19 @@ function isTiptapActive(editor, id) {
87
90
  * - WYSIWYG: calls Tiptap chain commands (toggleBold, etc.)
88
91
  * - Raw: appends markdown syntax to the source
89
92
  */
90
- export function Toolbar({ className, showFiles, onToggleFiles, slotLeft, slotAfterActions, slotRight, }) {
91
- const { activeView, setActiveView, markdownSource, setMarkdownSource, tiptapEditor, monacoEditor, mediaProvider, } = useEditorContext();
93
+ export function Toolbar({ className, showFiles, onToggleFiles, slotLeft, slotAfterActions, slotRight, showPlayTab = true, }) {
94
+ const { activeView, setActiveView, markdownSource, setMarkdownSource, tiptapEditor, monacoEditor, mediaProvider, editorMode, } = useEditorContext();
95
+ const isCodeMode = editorMode === 'code';
96
+ // In code mode only the raw view is meaningful; the WYSIWYG and Preview
97
+ // surfaces aren't mounted, so hide their tabs.
98
+ const visibleViews = VIEWS.filter((v) => {
99
+ if (isCodeMode)
100
+ return v.id === 'raw';
101
+ if (v.id === 'preview' && !showPlayTab)
102
+ return false;
103
+ return true;
104
+ });
105
+ const showViewTabs = visibleViews.length > 1;
92
106
  // Hidden file input for image picker
93
107
  const imageInputRef = useRef(null);
94
108
  // ── Narrow-screen detection ──────────────────────────
@@ -144,6 +158,31 @@ export function Toolbar({ className, showFiles, onToggleFiles, slotLeft, slotAft
144
158
  document.addEventListener('mousedown', handleClick);
145
159
  return () => document.removeEventListener('mousedown', handleClick);
146
160
  }, [showOverflow]);
161
+ // Open-up vs open-down: the overflow menu is anchored to its trigger with
162
+ // `top: 100%` by default. When the toolbar lives near the bottom of a
163
+ // small container (e.g. a chat composer), a downward menu gets clipped.
164
+ // Measure on open and flip the anchor to `bottom: 100%` if the space
165
+ // above the trigger is larger than the space below.
166
+ const [overflowPlacement, setOverflowPlacement] = useState('down');
167
+ useEffect(() => {
168
+ if (!showOverflow || !overflowRef.current)
169
+ return;
170
+ const trigger = overflowRef.current.querySelector('.squisq-toolbar-overflow-trigger');
171
+ if (!trigger)
172
+ return;
173
+ const rect = trigger.getBoundingClientRect();
174
+ const spaceBelow = window.innerHeight - rect.bottom;
175
+ const spaceAbove = rect.top;
176
+ // Assume a typical menu height; exact measurement is unreliable on first
177
+ // open because the menu hasn't rendered yet when this runs.
178
+ const ESTIMATED_MENU_HEIGHT = 260;
179
+ if (spaceBelow < ESTIMATED_MENU_HEIGHT && spaceAbove > spaceBelow) {
180
+ setOverflowPlacement('up');
181
+ }
182
+ else {
183
+ setOverflowPlacement('down');
184
+ }
185
+ }, [showOverflow]);
147
186
  // Force re-render when Tiptap selection or formatting state changes
148
187
  const [, forceUpdate] = useReducer((c) => c + 1, 0);
149
188
  useEffect(() => {
@@ -404,7 +443,7 @@ export function Toolbar({ className, showFiles, onToggleFiles, slotLeft, slotAft
404
443
  handleRaw(id);
405
444
  }
406
445
  }, [activeView, tiptapEditor, handleTiptap, handleRaw]);
407
- const groups = ['format', 'structure', 'insert'];
446
+ const groups = ['format', 'lists', 'structure', 'insert', 'media'];
408
447
  const isWysiwyg = activeView === 'wysiwyg' && tiptapEditor;
409
448
  const isPreview = activeView === 'preview';
410
449
  // Detect whether cursor is inside a table (WYSIWYG mode only)
@@ -436,14 +475,14 @@ export function Toolbar({ className, showFiles, onToggleFiles, slotLeft, slotAft
436
475
  handleImageFile(file);
437
476
  // Reset so the same file can be re-selected
438
477
  e.target.value = '';
439
- } }), slotLeft, _jsx("div", { className: "squisq-toolbar-view-tabs", role: "tablist", "aria-label": "Editor view", children: VIEWS.map((view) => (_jsx("button", { role: "tab", "data-view": view.id, "data-label": view.label, "aria-selected": activeView === view.id, className: `squisq-toolbar-view-tab${activeView === view.id ? ' squisq-toolbar-view-tab--active' : ''}`, onClick: () => setActiveView(view.id), title: `${view.label} (${view.shortcut})`, children: view.label }, view.id))) }), !isPreview && !isNarrow && (_jsxs("div", { className: "squisq-toolbar-actions", ref: actionsRef, children: [groups.map((group, gi) => (_jsxs("div", { className: "squisq-toolbar-group", children: [gi > 0 && _jsx("div", { className: "squisq-toolbar-separator" }), BUTTONS.filter((b) => b.group === group).map((btn) => {
478
+ } }), slotLeft, showViewTabs && (_jsx("div", { className: "squisq-toolbar-view-tabs", role: "tablist", "aria-label": "Editor view", children: visibleViews.map((view) => (_jsxs("button", { role: "tab", "data-view": view.id, "aria-selected": activeView === view.id, className: `squisq-toolbar-view-tab${activeView === view.id ? ' squisq-toolbar-view-tab--active' : ''}`, onClick: () => setActiveView(view.id), "data-tooltip": `${view.label} (${view.shortcut})`, children: [_jsx("span", { className: "squisq-toolbar-view-tab-label squisq-toolbar-view-tab-label--long", "data-label": view.label, children: view.label }), view.shortLabel && view.shortLabel !== view.label && (_jsx("span", { className: "squisq-toolbar-view-tab-label squisq-toolbar-view-tab-label--short", "data-label": view.shortLabel, children: view.shortLabel }))] }, view.id))) })), !isPreview && !isNarrow && !isCodeMode && (_jsxs("div", { className: "squisq-toolbar-actions", ref: actionsRef, children: [groups.map((group, gi) => (_jsxs("div", { className: "squisq-toolbar-group", children: [gi > 0 && _jsx("div", { className: "squisq-toolbar-separator" }), BUTTONS.filter((b) => b.group === group).map((btn) => {
440
479
  const active = isWysiwyg ? isTiptapActive(tiptapEditor, btn.id) : false;
441
480
  const disabled = btn.id === 'image' && !mediaProvider;
442
- return (_jsx("button", { className: `squisq-toolbar-button${active ? ' squisq-toolbar-button--active' : ''}`, title: disabled ? 'Insert image (requires media provider)' : btn.title, onClick: () => handleAction(btn.id), "aria-label": btn.title, "aria-pressed": active, disabled: disabled, style: btn.iconStyle, children: btn.id === 'table' ? (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "1", width: "12", height: "12", rx: "1" }), _jsx("line", { x1: "1", y1: "5", x2: "13", y2: "5" }), _jsx("line", { x1: "1", y1: "9", x2: "13", y2: "9" }), _jsx("line", { x1: "5", y1: "1", x2: "5", y2: "13" }), _jsx("line", { x1: "9", y1: "1", x2: "9", y2: "13" })] })) : (btn.icon) }, btn.id));
443
- })] }, group))), currentTemplate !== null && (_jsxs(_Fragment, { children: [_jsx("div", { className: "squisq-toolbar-separator" }), _jsx("div", { className: "squisq-toolbar-group squisq-template-picker", children: _jsxs("label", { className: "squisq-template-picker-label", title: "Block template for this heading", children: ["Template:", _jsxs("select", { className: "squisq-template-picker-select", value: currentTemplate, onChange: (e) => handleTemplatePick(e.target.value), children: [_jsx("option", { value: "", children: "\u2014 none \u2014" }), TEMPLATE_NAMES.map((name) => (_jsx("option", { value: name, children: name }, name)))] })] }) })] })), isInTable && (_jsxs(_Fragment, { children: [_jsx("div", { className: "squisq-toolbar-separator" }), _jsxs("div", { className: "squisq-toolbar-group squisq-table-controls", children: [_jsx("span", { className: "squisq-table-controls-label", children: "Table:" }), _jsx("button", { className: "squisq-toolbar-button", title: "Add column before", onClick: () => tiptapEditor.chain().focus().addColumnBefore().run(), "aria-label": "Add column before", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "7", y: "2", width: "8", height: "12", rx: "1" }), _jsx("line", { x1: "11", y1: "2", x2: "11", y2: "14" }), _jsx("line", { x1: "1", y1: "8", x2: "4.5", y2: "8" }), _jsx("line", { x1: "2.75", y1: "6.25", x2: "2.75", y2: "9.75" })] }) }), _jsx("button", { className: "squisq-toolbar-button", title: "Add column after", onClick: () => tiptapEditor.chain().focus().addColumnAfter().run(), "aria-label": "Add column after", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "2", width: "8", height: "12", rx: "1" }), _jsx("line", { x1: "5", y1: "2", x2: "5", y2: "14" }), _jsx("line", { x1: "11.5", y1: "8", x2: "15", y2: "8" }), _jsx("line", { x1: "13.25", y1: "6.25", x2: "13.25", y2: "9.75" })] }) }), _jsx("button", { className: "squisq-toolbar-button", title: "Delete column", onClick: () => tiptapEditor.chain().focus().deleteColumn().run(), "aria-label": "Delete column", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "4", y: "1", width: "8", height: "14", rx: "1" }), _jsx("line", { x1: "6", y1: "5.5", x2: "10", y2: "10.5" }), _jsx("line", { x1: "10", y1: "5.5", x2: "6", y2: "10.5" })] }) }), _jsx("button", { className: "squisq-toolbar-button", title: "Add row above", onClick: () => tiptapEditor.chain().focus().addRowBefore().run(), "aria-label": "Add row above", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "6", width: "12", height: "9", rx: "1" }), _jsx("line", { x1: "2", y1: "10.5", x2: "14", y2: "10.5" }), _jsx("line", { x1: "8", y1: "1", x2: "8", y2: "4.5" }), _jsx("line", { x1: "6.25", y1: "2.75", x2: "9.75", y2: "2.75" })] }) }), _jsx("button", { className: "squisq-toolbar-button", title: "Add row below", onClick: () => tiptapEditor.chain().focus().addRowAfter().run(), "aria-label": "Add row below", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "1", width: "12", height: "9", rx: "1" }), _jsx("line", { x1: "2", y1: "5.5", x2: "14", y2: "5.5" }), _jsx("line", { x1: "8", y1: "11.5", x2: "8", y2: "15" }), _jsx("line", { x1: "6.25", y1: "13.25", x2: "9.75", y2: "13.25" })] }) }), _jsx("button", { className: "squisq-toolbar-button", title: "Delete row", onClick: () => tiptapEditor.chain().focus().deleteRow().run(), "aria-label": "Delete row", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "4", width: "14", height: "8", rx: "1" }), _jsx("line", { x1: "5.5", y1: "6", x2: "10.5", y2: "10" }), _jsx("line", { x1: "10.5", y1: "6", x2: "5.5", y2: "10" })] }) }), _jsx("button", { className: "squisq-toolbar-button squisq-toolbar-button--danger", title: "Delete table", onClick: () => tiptapEditor.chain().focus().deleteTable().run(), "aria-label": "Delete table", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "1", width: "14", height: "14", rx: "1" }), _jsx("line", { x1: "1", y1: "5.5", x2: "15", y2: "5.5" }), _jsx("line", { x1: "5.5", y1: "1", x2: "5.5", y2: "15" }), _jsx("line", { x1: "4.5", y1: "4.5", x2: "11.5", y2: "11.5", strokeWidth: "2" }), _jsx("line", { x1: "11.5", y1: "4.5", x2: "4.5", y2: "11.5", strokeWidth: "2" })] }) })] })] }))] })), !isPreview && overflowIndex !== null && (_jsxs("div", { className: "squisq-toolbar-overflow", ref: overflowRef, children: [_jsx("button", { className: `squisq-toolbar-button squisq-toolbar-overflow-trigger${showOverflow ? ' squisq-toolbar-button--active' : ''}`, title: "More actions", onClick: () => setShowOverflow((v) => !v), "aria-label": "More actions", "aria-expanded": showOverflow, children: "\u00B7\u00B7\u00B7" }), showOverflow && (_jsxs("div", { className: "squisq-toolbar-overflow-menu", children: [BUTTONS.slice(overflowIndex).map((btn) => {
481
+ return (_jsx("button", { className: `squisq-toolbar-button${active ? ' squisq-toolbar-button--active' : ''}`, "data-tooltip": disabled ? 'Insert image (requires media provider)' : btn.title, onClick: () => handleAction(btn.id), "aria-label": btn.title, "aria-pressed": active, disabled: disabled, style: btn.iconStyle, children: btn.id === 'table' ? (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "1", width: "12", height: "12", rx: "1" }), _jsx("line", { x1: "1", y1: "5", x2: "13", y2: "5" }), _jsx("line", { x1: "1", y1: "9", x2: "13", y2: "9" }), _jsx("line", { x1: "5", y1: "1", x2: "5", y2: "13" }), _jsx("line", { x1: "9", y1: "1", x2: "9", y2: "13" })] })) : (btn.icon) }, btn.id));
482
+ })] }, group))), currentTemplate !== null && (_jsxs(_Fragment, { children: [_jsx("div", { className: "squisq-toolbar-separator" }), _jsx("div", { className: "squisq-toolbar-group squisq-template-picker", children: _jsxs("label", { className: "squisq-template-picker-label", "data-tooltip": "Block template for this heading", children: ["Template:", _jsxs("select", { className: "squisq-template-picker-select", value: currentTemplate, onChange: (e) => handleTemplatePick(e.target.value), children: [_jsx("option", { value: "", children: "\u2014 none \u2014" }), TEMPLATE_NAMES.map((name) => (_jsx("option", { value: name, children: name }, name)))] })] }) })] })), isInTable && (_jsxs(_Fragment, { children: [_jsx("div", { className: "squisq-toolbar-separator" }), _jsxs("div", { className: "squisq-toolbar-group squisq-table-controls", children: [_jsx("span", { className: "squisq-table-controls-label", children: "Table:" }), _jsx("button", { className: "squisq-toolbar-button", "data-tooltip": "Add column before", onClick: () => tiptapEditor.chain().focus().addColumnBefore().run(), "aria-label": "Add column before", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "7", y: "2", width: "8", height: "12", rx: "1" }), _jsx("line", { x1: "11", y1: "2", x2: "11", y2: "14" }), _jsx("line", { x1: "1", y1: "8", x2: "4.5", y2: "8" }), _jsx("line", { x1: "2.75", y1: "6.25", x2: "2.75", y2: "9.75" })] }) }), _jsx("button", { className: "squisq-toolbar-button", "data-tooltip": "Add column after", onClick: () => tiptapEditor.chain().focus().addColumnAfter().run(), "aria-label": "Add column after", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "2", width: "8", height: "12", rx: "1" }), _jsx("line", { x1: "5", y1: "2", x2: "5", y2: "14" }), _jsx("line", { x1: "11.5", y1: "8", x2: "15", y2: "8" }), _jsx("line", { x1: "13.25", y1: "6.25", x2: "13.25", y2: "9.75" })] }) }), _jsx("button", { className: "squisq-toolbar-button", "data-tooltip": "Delete column", onClick: () => tiptapEditor.chain().focus().deleteColumn().run(), "aria-label": "Delete column", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "4", y: "1", width: "8", height: "14", rx: "1" }), _jsx("line", { x1: "6", y1: "5.5", x2: "10", y2: "10.5" }), _jsx("line", { x1: "10", y1: "5.5", x2: "6", y2: "10.5" })] }) }), _jsx("button", { className: "squisq-toolbar-button", "data-tooltip": "Add row above", onClick: () => tiptapEditor.chain().focus().addRowBefore().run(), "aria-label": "Add row above", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "6", width: "12", height: "9", rx: "1" }), _jsx("line", { x1: "2", y1: "10.5", x2: "14", y2: "10.5" }), _jsx("line", { x1: "8", y1: "1", x2: "8", y2: "4.5" }), _jsx("line", { x1: "6.25", y1: "2.75", x2: "9.75", y2: "2.75" })] }) }), _jsx("button", { className: "squisq-toolbar-button", "data-tooltip": "Add row below", onClick: () => tiptapEditor.chain().focus().addRowAfter().run(), "aria-label": "Add row below", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "1", width: "12", height: "9", rx: "1" }), _jsx("line", { x1: "2", y1: "5.5", x2: "14", y2: "5.5" }), _jsx("line", { x1: "8", y1: "11.5", x2: "8", y2: "15" }), _jsx("line", { x1: "6.25", y1: "13.25", x2: "9.75", y2: "13.25" })] }) }), _jsx("button", { className: "squisq-toolbar-button", "data-tooltip": "Delete row", onClick: () => tiptapEditor.chain().focus().deleteRow().run(), "aria-label": "Delete row", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "4", width: "14", height: "8", rx: "1" }), _jsx("line", { x1: "5.5", y1: "6", x2: "10.5", y2: "10" }), _jsx("line", { x1: "10.5", y1: "6", x2: "5.5", y2: "10" })] }) }), _jsx("button", { className: "squisq-toolbar-button squisq-toolbar-button--danger", "data-tooltip": "Delete table", onClick: () => tiptapEditor.chain().focus().deleteTable().run(), "aria-label": "Delete table", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "1", width: "14", height: "14", rx: "1" }), _jsx("line", { x1: "1", y1: "5.5", x2: "15", y2: "5.5" }), _jsx("line", { x1: "5.5", y1: "1", x2: "5.5", y2: "15" }), _jsx("line", { x1: "4.5", y1: "4.5", x2: "11.5", y2: "11.5", strokeWidth: "2" }), _jsx("line", { x1: "11.5", y1: "4.5", x2: "4.5", y2: "11.5", strokeWidth: "2" })] }) })] })] }))] })), !isPreview && !isCodeMode && overflowIndex !== null && (_jsxs("div", { className: "squisq-toolbar-overflow", ref: overflowRef, children: [_jsx("button", { className: `squisq-toolbar-button squisq-toolbar-overflow-trigger${showOverflow ? ' squisq-toolbar-button--active' : ''}`, "data-tooltip": "More actions", onClick: () => setShowOverflow((v) => !v), "aria-label": "More actions", "aria-expanded": showOverflow, children: "\u00B7\u00B7\u00B7" }), showOverflow && (_jsxs("div", { className: `squisq-toolbar-overflow-menu squisq-toolbar-overflow-menu--${overflowPlacement}`, children: [BUTTONS.slice(overflowIndex).map((btn) => {
444
483
  const active = isWysiwyg ? isTiptapActive(tiptapEditor, btn.id) : false;
445
484
  const disabled = btn.id === 'image' && !mediaProvider;
446
- return (_jsxs("button", { className: `squisq-toolbar-overflow-item${active ? ' squisq-toolbar-overflow-item--active' : ''}`, title: btn.title, onClick: () => {
485
+ return (_jsxs("button", { className: `squisq-toolbar-overflow-item${active ? ' squisq-toolbar-overflow-item--active' : ''}`, onClick: () => {
447
486
  handleAction(btn.id);
448
487
  setShowOverflow(false);
449
488
  }, disabled: disabled, children: [btn.id === 'table' ? (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "1", width: "12", height: "12", rx: "1" }), _jsx("line", { x1: "1", y1: "5", x2: "13", y2: "5" }), _jsx("line", { x1: "1", y1: "9", x2: "13", y2: "9" }), _jsx("line", { x1: "5", y1: "1", x2: "5", y2: "13" }), _jsx("line", { x1: "9", y1: "1", x2: "9", y2: "13" })] })) : (_jsx("span", { className: "squisq-toolbar-overflow-icon", style: btn.iconStyle, children: btn.icon })), _jsx("span", { children: btn.title })] }, btn.id));
@@ -482,6 +521,6 @@ export function Toolbar({ className, showFiles, onToggleFiles, slotLeft, slotAft
482
521
  ].map((item) => (_jsx("button", { className: `squisq-toolbar-overflow-item${item.label.startsWith('Delete') ? ' squisq-toolbar-overflow-item--danger' : ''}`, onClick: () => {
483
522
  item.action();
484
523
  setShowOverflow(false);
485
- }, children: _jsx("span", { children: item.label }) }, item.label)))] }))] }))] })), slotAfterActions, _jsx("div", { style: { flex: 1 } }), onToggleFiles && (_jsx("button", { className: `squisq-toolbar-button squisq-toolbar-files-toggle${showFiles ? ' squisq-toolbar-button--active' : ''}`, onClick: onToggleFiles, title: showFiles ? 'Hide Files panel' : 'Show Files panel', "aria-pressed": showFiles, "aria-label": "Toggle Files panel", children: '\u{1F4CE}' })), slotRight] }));
524
+ }, children: _jsx("span", { children: item.label }) }, item.label)))] }))] }))] })), slotAfterActions, (isPreview || isNarrow || isCodeMode) && _jsx("div", { style: { flex: 1 } }), onToggleFiles && (_jsx("button", { className: `squisq-toolbar-button squisq-toolbar-files-toggle${showFiles ? ' squisq-toolbar-button--active' : ''}`, onClick: onToggleFiles, "data-tooltip": showFiles ? 'Hide Files panel' : 'Show Files panel', "aria-pressed": showFiles, "aria-label": "Toggle Files panel", children: '\u{1F4CE}' })), slotRight] }));
486
525
  }
487
526
  //# sourceMappingURL=Toolbar.js.map