@bendyline/squisq-editor-react 1.6.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 (208) hide show
  1. package/README.md +12 -3
  2. package/dist/index.d.ts +1304 -208
  3. package/dist/index.js +22838 -14494
  4. package/dist/index.js.map +1 -1
  5. package/dist/monaco.d.ts +1 -0
  6. package/dist/monaco.js +4 -0
  7. package/dist/monaco.js.map +1 -0
  8. package/dist/styles/index.css +2384 -408
  9. package/package.json +9 -5
  10. package/src/BlockPropertiesPopover.tsx +48 -17
  11. package/src/DocumentSettingsDialog.tsx +13 -21
  12. package/src/EditorContext.tsx +199 -42
  13. package/src/EditorShell.tsx +403 -270
  14. package/src/ImageEditor.tsx +22 -1
  15. package/src/InlinePreviewGutter.tsx +16 -8
  16. package/src/MediaBin.tsx +276 -40
  17. package/src/OutlinePanel.tsx +202 -7
  18. package/src/PlainHtmlPreview.tsx +40 -1
  19. package/src/PreviewControls.tsx +466 -93
  20. package/src/PreviewPanel.tsx +313 -77
  21. package/src/RawEditor.tsx +13 -2
  22. package/src/StatusBar.tsx +5 -2
  23. package/src/TemplateAnnotation.ts +34 -10
  24. package/src/TemplateContentPreview.tsx +56 -0
  25. package/src/TemplatePicker.tsx +355 -134
  26. package/src/ThemeCustomizerPanel.tsx +30 -15
  27. package/src/ThemePicker.tsx +10 -5
  28. package/src/TimelineBlockPreview.tsx +1 -1
  29. package/src/Toolbar.tsx +719 -238
  30. package/src/TransitionPicker.tsx +44 -5
  31. package/src/ViewMenuPanel.tsx +12 -14
  32. package/src/ViewSwitcher.tsx +4 -4
  33. package/src/WysiwygEditor.tsx +167 -92
  34. package/src/__tests__/blockPropertiesPopoverTheme.test.tsx +33 -0
  35. package/src/__tests__/blockTagActivity.test.ts +183 -0
  36. package/src/__tests__/buildDocumentPreviewMarkdown.test.ts +75 -0
  37. package/src/__tests__/buildPreviewDocContent.test.ts +48 -0
  38. package/src/__tests__/buildPreviewDocTransition.test.ts +22 -3
  39. package/src/__tests__/canvasSurfaceTextEditing.test.tsx +60 -0
  40. package/src/__tests__/customLayoutManagerTheme.test.tsx +34 -0
  41. package/src/__tests__/documentSettingsDialog.test.tsx +29 -1
  42. package/src/__tests__/editorScrollHandoff.test.tsx +102 -0
  43. package/src/__tests__/editorScrollSync.test.ts +65 -0
  44. package/src/__tests__/editorShellProps.test.tsx +390 -1
  45. package/src/__tests__/emojiPicker.test.tsx +2 -42
  46. package/src/__tests__/headingTransition.test.ts +53 -15
  47. package/src/__tests__/imageEditAffordance.test.tsx +5 -1
  48. package/src/__tests__/imageEditModalContract.test.tsx +119 -0
  49. package/src/__tests__/imageEditorShell.test.tsx +38 -1
  50. package/src/__tests__/jsonEditor.test.tsx +56 -1
  51. package/src/__tests__/layersPanel.test.tsx +75 -5
  52. package/src/__tests__/majorApiTypes.test.ts +26 -0
  53. package/src/__tests__/mediaBinDrop.test.tsx +90 -0
  54. package/src/__tests__/mediaReferences.test.ts +82 -0
  55. package/src/__tests__/narrationSave.test.ts +148 -0
  56. package/src/__tests__/outlinePanel.test.tsx +93 -3
  57. package/src/__tests__/outlineSource.test.ts +217 -0
  58. package/src/__tests__/plainHtmlPreview.test.tsx +17 -1
  59. package/src/__tests__/presentationMode.test.tsx +290 -0
  60. package/src/__tests__/previewControls.test.tsx +312 -6
  61. package/src/__tests__/previewPanelAudioFailure.test.tsx +46 -0
  62. package/src/__tests__/previewPanelPresentation.test.tsx +126 -0
  63. package/src/__tests__/previewPanelTransforms.test.tsx +117 -0
  64. package/src/__tests__/rawEditorModelIsolation.test.ts +19 -0
  65. package/src/__tests__/resolveBlockVisual.test.ts +43 -0
  66. package/src/__tests__/statusBar.test.tsx +27 -0
  67. package/src/__tests__/teleprompter.test.tsx +190 -0
  68. package/src/__tests__/templateAnnotationRoundTrip.test.ts +49 -2
  69. package/src/__tests__/templateContentPreview.test.ts +101 -0
  70. package/src/__tests__/templatePickerPortal.test.tsx +62 -0
  71. package/src/__tests__/tiptapBridge.test.ts +70 -0
  72. package/src/__tests__/tiptapCodeBlockRoundTrip.test.ts +109 -0
  73. package/src/__tests__/transformStyleId.test.ts +13 -0
  74. package/src/__tests__/useImageEditor.test.tsx +67 -0
  75. package/src/__tests__/useMediaRecorder.test.ts +75 -0
  76. package/src/__tests__/viewMenuPanel.test.tsx +130 -0
  77. package/src/__tests__/wysiwygImageUpload.test.ts +69 -0
  78. package/src/__tests__/wysiwygTemplateBadgeFocus.test.tsx +56 -0
  79. package/src/asciiDiagram/AsciiDiagramExtension.ts +343 -0
  80. package/src/asciiDiagram/AsciiDiagramWidget.tsx +224 -0
  81. package/src/asciiDiagram/RepairableDiagramExtension.ts +200 -0
  82. package/src/asciiDiagram/__tests__/AsciiDiagramExtension.test.ts +145 -0
  83. package/src/asciiDiagram/__tests__/RepairableDiagramExtension.test.ts +159 -0
  84. package/src/asciiDiagram/__tests__/asciiDiagramCommands.test.ts +227 -0
  85. package/src/asciiDiagram/__tests__/asciiDiagramOps.test.ts +114 -0
  86. package/src/asciiDiagram/__tests__/asciiPaste.test.ts +43 -0
  87. package/src/asciiDiagram/asciiDiagramCommands.ts +148 -0
  88. package/src/asciiDiagram/asciiDiagramData.ts +116 -0
  89. package/src/asciiDiagram/asciiDiagramOps.ts +219 -0
  90. package/src/asciiDiagram/asciiPaste.ts +19 -0
  91. package/src/blockTagActivity.ts +233 -0
  92. package/src/buildDocumentPreviewMarkdown.ts +168 -0
  93. package/src/buildPreviewDoc.ts +19 -12
  94. package/src/customTemplates/CustomLayoutManager.tsx +3 -2
  95. package/src/customTemplates/CustomTemplateContext.tsx +6 -0
  96. package/src/customTemplates/TemplateDesigner.tsx +7 -4
  97. package/src/customTemplates/__tests__/library.test.ts +8 -0
  98. package/src/customTemplates/designer.css +158 -99
  99. package/src/customTemplates/library.ts +16 -3
  100. package/src/customThemes/CustomThemeContext.tsx +6 -0
  101. package/src/customThemes/CustomThemeDialog.tsx +35 -5
  102. package/src/customThemes/ImportThemeSection.tsx +178 -0
  103. package/src/customThemes/__tests__/customThemeLibrary.test.ts +9 -0
  104. package/src/customThemes/__tests__/importThemeSection.test.tsx +192 -0
  105. package/src/customThemes/customThemeLibrary.ts +7 -4
  106. package/src/customThemes/index.ts +7 -1
  107. package/src/customThemes/themeDraft.ts +23 -7
  108. package/src/diagram/DiagramCanvas.tsx +9 -4
  109. package/src/diagram/types.ts +35 -0
  110. package/src/editorScrollSync.ts +73 -0
  111. package/src/emojiData.ts +3 -23
  112. package/src/headingTransition.ts +85 -25
  113. package/src/imageEditor/CanvasSurface.tsx +29 -23
  114. package/src/imageEditor/LayersPanel.tsx +78 -3
  115. package/src/imageEditor/Toolbar.tsx +5 -1
  116. package/src/imageEditor/icons.tsx +4 -0
  117. package/src/imageEditor/image-editor.css +75 -0
  118. package/src/imageEditor/layers/SelectionHandles.tsx +1 -1
  119. package/src/imageEditor/useImageEditor.ts +71 -14
  120. package/src/index.ts +193 -20
  121. package/src/jsonEditor/JsonEditorContext.tsx +12 -6
  122. package/src/jsonEditor/RenderNode.tsx +24 -3
  123. package/src/jsonEditor/editors.tsx +86 -19
  124. package/src/mediaEntries.ts +12 -0
  125. package/src/mediaReferences.ts +299 -0
  126. package/src/monaco.ts +35 -0
  127. package/src/monacoWorkers.ts +89 -0
  128. package/src/outlineSource.ts +171 -0
  129. package/src/presentation/PresentationMode.tsx +596 -0
  130. package/src/rawEditorIsolation.ts +18 -0
  131. package/src/recorder/hooks/useMediaRecorder.ts +97 -53
  132. package/src/resolveBlockVisual.ts +10 -4
  133. package/src/scene/Scene.tsx +101 -25
  134. package/src/scene/SceneBlockExtension.ts +17 -10
  135. package/src/scene/SceneBlockWidget.tsx +11 -4
  136. package/src/scene/SceneSelection.tsx +19 -15
  137. package/src/scene/SceneSideToolbar.tsx +89 -0
  138. package/src/scene/SceneViewport.tsx +7 -3
  139. package/src/scene/ShapePalette.tsx +17 -2
  140. package/src/scene/__tests__/DiagramAdapter.test.ts +86 -0
  141. package/src/scene/__tests__/SceneBlockExtension.test.ts +33 -0
  142. package/src/scene/__tests__/sceneIsolation.test.tsx +93 -0
  143. package/src/scene/adapters/DiagramAdapter.ts +12 -101
  144. package/src/scene/commands/SceneCommand.ts +4 -1
  145. package/src/scene/index.ts +1 -6
  146. package/src/scene/layers/DiagramEdges.tsx +24 -9
  147. package/src/scene/layers/edgeGeometry.ts +31 -4
  148. package/src/scene/layers/nodeCard.tsx +27 -8
  149. package/src/scene/scene.css +145 -2
  150. package/src/scene/text/SceneTextOverlay.tsx +5 -5
  151. package/src/scene/text/sceneTextChannel.ts +26 -20
  152. package/src/scene/text/sceneTextConfig.ts +4 -0
  153. package/src/scene/tools/ConnectTool.ts +126 -28
  154. package/src/scene/tools/DrawingConnectTool.ts +86 -16
  155. package/src/scene/tools/SceneTool.ts +10 -0
  156. package/src/scene/tools/SelectTool.ts +34 -18
  157. package/src/scene/tools/ShapeTool.ts +2 -3
  158. package/src/styles/ascii-diagram.css +79 -0
  159. package/src/styles/ascii-timeline.css +499 -0
  160. package/src/styles/editor.css +1566 -219
  161. package/src/styles/index.css +3 -0
  162. package/src/styles/tree-view.css +139 -0
  163. package/src/teleprompter/TeleprompterControls.tsx +218 -0
  164. package/src/teleprompter/TeleprompterSelfView.tsx +22 -0
  165. package/src/teleprompter/TeleprompterSurface.tsx +267 -0
  166. package/src/teleprompter/TeleprompterView.tsx +338 -0
  167. package/src/teleprompter/canvasRenderer.ts +161 -0
  168. package/src/teleprompter/floatingWindow.ts +352 -0
  169. package/src/teleprompter/index.ts +61 -0
  170. package/src/teleprompter/pcmWorklet.ts +62 -0
  171. package/src/teleprompter/recording/insertPreamble.ts +80 -0
  172. package/src/teleprompter/recording/narrationSave.ts +134 -0
  173. package/src/teleprompter/recording/useNarrationRecorder.ts +367 -0
  174. package/src/teleprompter/scrollModel.ts +85 -0
  175. package/src/teleprompter/teleprompterTheme.ts +303 -0
  176. package/src/teleprompter/types.ts +38 -0
  177. package/src/teleprompter/useFloatingWindow.ts +74 -0
  178. package/src/teleprompter/useMicAnalysis.ts +211 -0
  179. package/src/teleprompter/useTeleprompter.ts +421 -0
  180. package/src/templateContentPreviewResolver.ts +360 -0
  181. package/src/timeline/TimelineEditorWidget.tsx +702 -0
  182. package/src/timeline/TimelineViewExtension.ts +252 -0
  183. package/src/timeline/__tests__/TimelineEditorWidget.test.tsx +355 -0
  184. package/src/timeline/__tests__/TimelineViewExtension.test.ts +163 -0
  185. package/src/timeline/__tests__/timelineCommands.test.ts +327 -0
  186. package/src/timeline/__tests__/timelineOps.test.ts +222 -0
  187. package/src/timeline/__tests__/timelinePaste.test.ts +34 -0
  188. package/src/timeline/timelineCommands.ts +367 -0
  189. package/src/timeline/timelineData.ts +54 -0
  190. package/src/timeline/timelineOps.ts +277 -0
  191. package/src/timeline/timelinePaste.ts +8 -0
  192. package/src/tiptapBridge.ts +84 -49
  193. package/src/transformStyleId.ts +17 -0
  194. package/src/treeview/TreeOutlineWidget.tsx +240 -0
  195. package/src/treeview/TreeViewExtension.ts +250 -0
  196. package/src/treeview/__tests__/TreeViewExtension.test.ts +122 -0
  197. package/src/treeview/__tests__/treeOps.test.ts +125 -0
  198. package/src/treeview/__tests__/treePaste.test.ts +40 -0
  199. package/src/treeview/__tests__/treeViewCommands.test.ts +163 -0
  200. package/src/treeview/treeOps.ts +172 -0
  201. package/src/treeview/treePaste.ts +13 -0
  202. package/src/treeview/treeViewCommands.ts +94 -0
  203. package/src/treeview/treeViewData.ts +41 -0
  204. package/src/useMonacoLoader.ts +11 -34
  205. package/src/wysiwygImageUpload.ts +113 -0
  206. package/src/diagram/DiagramExtension.ts +0 -209
  207. package/src/diagram/DiagramWidget.tsx +0 -270
  208. package/src/diagram/useDiagramData.ts +0 -126
@@ -40,6 +40,7 @@ import {
40
40
  type ImageTreatmentPreset,
41
41
  } from './customThemes/themeDraft';
42
42
  import { Section, SeedColorRow, FontPicker, PresetRow } from './customThemes/themeControls';
43
+ import { ImportThemeSection } from './customThemes/ImportThemeSection';
43
44
 
44
45
  // ── Component ───────────────────────────────────────────────────────
45
46
 
@@ -52,6 +53,8 @@ export interface ThemeCustomizerPanelProps {
52
53
  onSave?: (theme: Theme, json: string) => void;
53
54
  /** Fired when the user clicks Reset. Host typically clears its persistent storage. */
54
55
  onReset?: () => void;
56
+ /** Optional text trigger. Omit to use the compact icon trigger. */
57
+ triggerLabel?: string;
55
58
  }
56
59
 
57
60
  export function ThemeCustomizerPanel({
@@ -59,6 +62,7 @@ export function ThemeCustomizerPanel({
59
62
  onChange,
60
63
  onSave,
61
64
  onReset,
65
+ triggerLabel,
62
66
  }: ThemeCustomizerPanelProps) {
63
67
  const [open, setOpen] = useState(false);
64
68
  const [draft, setDraft] = useState<Draft>(() => themeToDraft(value));
@@ -143,26 +147,30 @@ export function ThemeCustomizerPanel({
143
147
  <button
144
148
  type="button"
145
149
  className={`squisq-toolbar-button squisq-theme-customizer-trigger${
146
- open ? ' squisq-toolbar-button--active' : ''
147
- }`}
150
+ triggerLabel ? ' squisq-theme-customizer-trigger--label' : ''
151
+ }${open ? ' squisq-toolbar-button--active' : ''}`}
148
152
  data-tooltip="Customize theme"
149
153
  aria-label="Customize theme"
150
154
  aria-expanded={open}
151
155
  onClick={() => setOpen((v) => !v)}
152
156
  >
153
- <svg
154
- width="16"
155
- height="16"
156
- viewBox="0 0 16 16"
157
- fill="none"
158
- stroke="currentColor"
159
- strokeWidth="1.5"
160
- strokeLinecap="round"
161
- strokeLinejoin="round"
162
- >
163
- <circle cx="8" cy="8" r="6" />
164
- <path d="M8 2 A6 6 0 0 1 8 14 Z" fill="currentColor" stroke="none" />
165
- </svg>
157
+ {triggerLabel ? (
158
+ <span className="squisq-theme-customizer-trigger-label">{triggerLabel}</span>
159
+ ) : (
160
+ <svg
161
+ width="16"
162
+ height="16"
163
+ viewBox="0 0 16 16"
164
+ fill="none"
165
+ stroke="currentColor"
166
+ strokeWidth="1.5"
167
+ strokeLinecap="round"
168
+ strokeLinejoin="round"
169
+ >
170
+ <circle cx="8" cy="8" r="6" />
171
+ <path d="M8 2 A6 6 0 0 1 8 14 Z" fill="currentColor" stroke="none" />
172
+ </svg>
173
+ )}
166
174
  </button>
167
175
  {open && (
168
176
  <div className="squisq-theme-customizer-popover" role="dialog" aria-label="Customize theme">
@@ -181,6 +189,13 @@ export function ThemeCustomizerPanel({
181
189
  />
182
190
  </Section>
183
191
 
192
+ <Section
193
+ title="Import from file"
194
+ hint="Pull colors and fonts from a Word, PowerPoint, or Excel file."
195
+ >
196
+ <ImportThemeSection onImported={(patch) => updateDraft(patch)} />
197
+ </Section>
198
+
184
199
  <Section title="Colors" hint="Pick seed colors. The rest is derived.">
185
200
  <SeedColorRow
186
201
  label="Primary"
@@ -9,7 +9,7 @@
9
9
  * preview-on-hover style listing rather than a wall of names.
10
10
  */
11
11
 
12
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
12
+ import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
13
13
  import { createPortal } from 'react-dom';
14
14
  import {
15
15
  getThemeSummaries,
@@ -95,6 +95,7 @@ function ThemeNameChip({
95
95
  return (
96
96
  <span
97
97
  className={`squisq-theme-picker-name-chip${className ? ` ${className}` : ''}`}
98
+ data-theme-id={theme.id}
98
99
  style={{
99
100
  background: theme.colors.background,
100
101
  color: theme.colors.text,
@@ -102,7 +103,7 @@ function ThemeNameChip({
102
103
  borderColor: theme.colors.backgroundLight,
103
104
  }}
104
105
  >
105
- {label}
106
+ <span className="squisq-theme-picker-name-chip-label">{label}</span>
106
107
  </span>
107
108
  );
108
109
  }
@@ -133,6 +134,8 @@ export function ThemePicker({
133
134
  const [open, setOpen] = useState(false);
134
135
  const [popoverStyle, setPopoverStyle] = useState<React.CSSProperties>({});
135
136
  const triggerRef = useRef<HTMLButtonElement>(null);
137
+ const popoverRef = useRef<HTMLDivElement>(null);
138
+ const popoverId = `squisq-theme-picker-popover-${useId().replace(/:/g, '')}`;
136
139
 
137
140
  // Custom entries are computed per-render (built-ins stay static at module
138
141
  // load). A custom theme is already a full Theme, so it becomes an entry
@@ -189,7 +192,7 @@ export function ThemePicker({
189
192
  // trigger as-is. On the first open it doesn't exist yet — we'll
190
193
  // re-run after mount via the requestAnimationFrame in the open
191
194
  // effect, so estimate generously for paint #1.
192
- const popoverEl = document.getElementById('squisq-theme-picker-popover');
195
+ const popoverEl = popoverRef.current;
193
196
  const measured = popoverEl?.scrollHeight ?? 520;
194
197
  const spaceBelow = vh - rect.bottom - margin - gap;
195
198
  const spaceAbove = rect.top - margin - gap;
@@ -229,7 +232,7 @@ export function ThemePicker({
229
232
  const onDown = (e: MouseEvent) => {
230
233
  const target = e.target as Node;
231
234
  if (triggerRef.current?.contains(target)) return;
232
- const popoverEl = document.getElementById('squisq-theme-picker-popover');
235
+ const popoverEl = popoverRef.current;
233
236
  if (popoverEl?.contains(target)) return;
234
237
  setOpen(false);
235
238
  };
@@ -258,7 +261,8 @@ export function ThemePicker({
258
261
  const popover = open
259
262
  ? createPortal(
260
263
  <div
261
- id="squisq-theme-picker-popover"
264
+ ref={popoverRef}
265
+ id={popoverId}
262
266
  className="squisq-theme-picker-popover"
263
267
  role="listbox"
264
268
  aria-label={ariaLabel}
@@ -392,6 +396,7 @@ export function ThemePicker({
392
396
  onClick={handleToggle}
393
397
  aria-haspopup="listbox"
394
398
  aria-expanded={open}
399
+ aria-controls={open ? popoverId : undefined}
395
400
  aria-label={ariaLabel}
396
401
  >
397
402
  {previewEntry && (
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Renders a tiny slideshow-style thumbnail of a single block, used to fill each
5
5
  * bar on the timeline. Reuses the same rendering path as the inline preview
6
- * gutter and the slideshow: `buildPreviewDoc` → `getLayers` → `BlockRenderer`.
6
+ * gutter and the slideshow: `buildPreviewDoc` → `materializeBlockLayers` → `BlockRenderer`.
7
7
  */
8
8
 
9
9
  import { memo } from 'react';