@bendyline/squisq-editor-react 2.1.0 → 2.3.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.
- package/LICENSE +21 -0
- package/NOTICE.md +40 -0
- package/dist/chunk-54UGTQBO.js +862 -0
- package/dist/chunk-5JMHFAVW.js +2408 -0
- package/dist/chunk-5Q4JN4I5.js +132 -0
- package/dist/chunk-6VDYKI3L.js +49 -0
- package/dist/chunk-GS7QWYFT.js +9 -0
- package/dist/chunk-MJJK7YQB.js +949 -0
- package/dist/chunk-NITZVAXL.js +986 -0
- package/dist/chunk-TRCKHRBS.js +35234 -0
- package/dist/chunk-V44VP242.js +3256 -0
- package/dist/image-editor/index.d.ts +223 -0
- package/dist/image-editor/index.js +15 -0
- package/dist/index.d.ts +2060 -4040
- package/dist/index.js +496 -40014
- package/dist/json-editor/index.d.ts +27 -0
- package/dist/json-editor/index.js +7 -0
- package/dist/monaco.d.ts +1 -1
- package/dist/monaco.js +1 -2
- package/dist/recorder/index.d.ts +407 -0
- package/dist/recorder/index.js +43 -0
- package/dist/shell/index.d.ts +9 -0
- package/dist/shell/index.js +22 -0
- package/dist/shell-BxSCBm4H.d.ts +1064 -0
- package/dist/styles/index.css +598 -161
- package/dist/teleprompter/index.d.ts +497 -0
- package/dist/teleprompter/index.js +57 -0
- package/package.json +34 -8
- package/dist/index.js.map +0 -1
- package/dist/monaco.js.map +0 -1
- package/src/BlockCardView.tsx +0 -121
- package/src/BlockPreviewPanel.tsx +0 -69
- package/src/BlockPropertiesPopover.tsx +0 -222
- package/src/DocumentSettingsDialog.tsx +0 -272
- package/src/DropZoneOverlay.tsx +0 -137
- package/src/EditorContext.tsx +0 -1274
- package/src/EditorShell.tsx +0 -1358
- package/src/EmojiPicker.tsx +0 -332
- package/src/FolderView.tsx +0 -131
- package/src/Icon.tsx +0 -26
- package/src/ImageEditor.tsx +0 -395
- package/src/ImageNodeView.tsx +0 -284
- package/src/ImageViewer.tsx +0 -221
- package/src/InlineIcon.ts +0 -84
- package/src/InlinePreviewGutter.tsx +0 -590
- package/src/LinkDialog.tsx +0 -276
- package/src/MediaBin.tsx +0 -500
- package/src/MentionExtension.tsx +0 -261
- package/src/OutlinePanel.tsx +0 -547
- package/src/PlainHtmlPreview.tsx +0 -277
- package/src/PreviewControls.tsx +0 -1265
- package/src/PreviewPanel.tsx +0 -426
- package/src/RawEditor.tsx +0 -743
- package/src/RecorderEntry.tsx +0 -162
- package/src/StatusBar.tsx +0 -51
- package/src/TemplateAnnotation.ts +0 -167
- package/src/TemplateContentPreview.tsx +0 -56
- package/src/TemplatePicker.tsx +0 -1314
- package/src/ThemeCustomizerPanel.tsx +0 -304
- package/src/ThemePicker.tsx +0 -433
- package/src/TimelineBlockPreview.tsx +0 -37
- package/src/TimelineTrack.tsx +0 -671
- package/src/Toolbar.tsx +0 -2885
- package/src/Tooltip.tsx +0 -142
- package/src/TransitionPicker.tsx +0 -390
- package/src/VersionHistoryPanel.tsx +0 -359
- package/src/ViewMenuPanel.tsx +0 -189
- package/src/ViewSwitcher.tsx +0 -56
- package/src/WysiwygEditor.tsx +0 -806
- package/src/__tests__/blockProperties.test.ts +0 -92
- package/src/__tests__/blockPropertiesPopoverTheme.test.tsx +0 -33
- package/src/__tests__/blockRange.test.ts +0 -105
- package/src/__tests__/blockTagActivity.test.ts +0 -183
- package/src/__tests__/buildDocumentPreviewMarkdown.test.ts +0 -75
- package/src/__tests__/buildPreviewDocContent.test.ts +0 -65
- package/src/__tests__/buildPreviewDocTransition.test.ts +0 -92
- package/src/__tests__/canvasSurfaceTextEditing.test.tsx +0 -60
- package/src/__tests__/codeContextSectionView.test.tsx +0 -97
- package/src/__tests__/codeContextZoneManager.test.ts +0 -127
- package/src/__tests__/createShapeLayer.test.ts +0 -46
- package/src/__tests__/customLayoutManagerTheme.test.tsx +0 -34
- package/src/__tests__/detectMarkdown.test.ts +0 -73
- package/src/__tests__/diffContextSections.test.ts +0 -39
- package/src/__tests__/documentSettingsDialog.test.tsx +0 -197
- package/src/__tests__/drawingShapeRoundTrip.test.ts +0 -49
- package/src/__tests__/editorScrollHandoff.test.tsx +0 -102
- package/src/__tests__/editorScrollSync.test.ts +0 -65
- package/src/__tests__/editorShellCodeContext.test.tsx +0 -86
- package/src/__tests__/editorShellProps.test.tsx +0 -550
- package/src/__tests__/embeddedMedia.test.ts +0 -48
- package/src/__tests__/emojiPicker.test.tsx +0 -93
- package/src/__tests__/fileKind.test.ts +0 -112
- package/src/__tests__/findMode.test.tsx +0 -104
- package/src/__tests__/findModel.test.ts +0 -55
- package/src/__tests__/headingTransition.test.ts +0 -176
- package/src/__tests__/imageEditAffordance.test.tsx +0 -272
- package/src/__tests__/imageEditModalContract.test.tsx +0 -119
- package/src/__tests__/imageEditorShell.test.tsx +0 -94
- package/src/__tests__/imageEditorState.test.ts +0 -171
- package/src/__tests__/inlinePreviewGutter.test.tsx +0 -62
- package/src/__tests__/inlinePreviewGutterAllBlocks.test.tsx +0 -103
- package/src/__tests__/jsonEditor.test.tsx +0 -223
- package/src/__tests__/layersPanel.test.tsx +0 -167
- package/src/__tests__/layoutChildRoundTrip.test.ts +0 -71
- package/src/__tests__/linkDialogDocPicker.test.tsx +0 -137
- package/src/__tests__/majorApiTypes.test.ts +0 -26
- package/src/__tests__/markdownCodeFence.test.ts +0 -45
- package/src/__tests__/mediaAttachmentFlow.test.ts +0 -110
- package/src/__tests__/mediaBinDrop.test.tsx +0 -90
- package/src/__tests__/mediaReferences.test.ts +0 -97
- package/src/__tests__/narrationSave.test.ts +0 -148
- package/src/__tests__/outlinePanel.test.tsx +0 -169
- package/src/__tests__/outlineSource.test.ts +0 -217
- package/src/__tests__/plainHtmlPreview.test.tsx +0 -125
- package/src/__tests__/presentationMode.test.tsx +0 -290
- package/src/__tests__/previewControls.test.tsx +0 -571
- package/src/__tests__/previewPanelAudioFailure.test.tsx +0 -46
- package/src/__tests__/previewPanelPresentation.test.tsx +0 -126
- package/src/__tests__/previewPanelTransforms.test.tsx +0 -117
- package/src/__tests__/propertiesPanel.test.tsx +0 -69
- package/src/__tests__/rawEditorModelIsolation.test.ts +0 -19
- package/src/__tests__/recorderFormats.test.ts +0 -146
- package/src/__tests__/recorderMediaInsert.test.ts +0 -86
- package/src/__tests__/recorderTheme.test.tsx +0 -42
- package/src/__tests__/recorderTimingJson.test.ts +0 -41
- package/src/__tests__/resolveBlockVisual.test.ts +0 -43
- package/src/__tests__/selectionConversions.test.ts +0 -80
- package/src/__tests__/statusBar.test.tsx +0 -27
- package/src/__tests__/teleprompter.test.tsx +0 -190
- package/src/__tests__/templateAnnotationRoundTrip.test.ts +0 -99
- package/src/__tests__/templateContentPreview.test.ts +0 -101
- package/src/__tests__/templatePickerMetadata.test.ts +0 -32
- package/src/__tests__/templatePickerPortal.test.tsx +0 -62
- package/src/__tests__/timelineSource.test.ts +0 -134
- package/src/__tests__/tiptapBridge.test.ts +0 -575
- package/src/__tests__/tiptapBridgeConformance.test.ts +0 -47
- package/src/__tests__/tiptapCodeBlockRoundTrip.test.ts +0 -109
- package/src/__tests__/tiptapImageRoundTrip.test.ts +0 -73
- package/src/__tests__/toolbarSelectionConversion.test.tsx +0 -190
- package/src/__tests__/tooltip.test.tsx +0 -72
- package/src/__tests__/transformStyleId.test.ts +0 -13
- package/src/__tests__/transitionCatalog.test.ts +0 -64
- package/src/__tests__/useBlockNavigator.test.tsx +0 -67
- package/src/__tests__/useImageEditor.test.tsx +0 -226
- package/src/__tests__/useJsonEditorTokens.test.ts +0 -59
- package/src/__tests__/useMediaRecorder.test.ts +0 -302
- package/src/__tests__/useTimelineClock.test.ts +0 -21
- package/src/__tests__/versionHistory.test.tsx +0 -197
- package/src/__tests__/viewMenuPanel.test.tsx +0 -130
- package/src/__tests__/writeCanvasSettings.test.ts +0 -15
- package/src/__tests__/wysiwygImageUpload.test.ts +0 -69
- package/src/__tests__/wysiwygTemplateBadgeFocus.test.tsx +0 -56
- package/src/asciiDiagram/AsciiDiagramExtension.ts +0 -343
- package/src/asciiDiagram/AsciiDiagramWidget.tsx +0 -254
- package/src/asciiDiagram/RepairableDiagramExtension.ts +0 -200
- package/src/asciiDiagram/__tests__/AsciiDiagramExtension.test.ts +0 -164
- package/src/asciiDiagram/__tests__/RepairableDiagramExtension.test.ts +0 -159
- package/src/asciiDiagram/__tests__/asciiDiagramCommands.test.ts +0 -284
- package/src/asciiDiagram/__tests__/asciiDiagramOps.test.ts +0 -114
- package/src/asciiDiagram/__tests__/asciiPaste.test.ts +0 -43
- package/src/asciiDiagram/asciiDiagramCommands.ts +0 -174
- package/src/asciiDiagram/asciiDiagramData.ts +0 -149
- package/src/asciiDiagram/asciiDiagramOps.ts +0 -238
- package/src/asciiDiagram/asciiPaste.ts +0 -19
- package/src/blockProperties.ts +0 -88
- package/src/blockRange.ts +0 -132
- package/src/blockSlice.ts +0 -75
- package/src/blockTagActivity.ts +0 -233
- package/src/buildDocumentPreviewMarkdown.ts +0 -168
- package/src/buildPreviewDoc.ts +0 -407
- package/src/codeContext/CodeContextSectionView.tsx +0 -124
- package/src/codeContext/CodeContextZoneManager.ts +0 -149
- package/src/codeContext/CodeContextZones.tsx +0 -121
- package/src/codeContext/diffContextSections.ts +0 -38
- package/src/codeContext/types.ts +0 -75
- package/src/codeSnippet/CodeSnippetExtension.ts +0 -205
- package/src/codeSnippet/CodeSnippetWidget.tsx +0 -109
- package/src/codeSnippet/__tests__/CodeSnippetExtension.test.ts +0 -95
- package/src/codeSnippet/__tests__/codeSnippetLanguages.test.ts +0 -50
- package/src/codeSnippet/codeSnippetCommands.ts +0 -21
- package/src/codeSnippet/codeSnippetData.ts +0 -43
- package/src/codeSnippet/codeSnippetLanguages.ts +0 -216
- package/src/customTemplates/AddBin.tsx +0 -126
- package/src/customTemplates/CustomLayoutManager.tsx +0 -234
- package/src/customTemplates/CustomTemplateContext.tsx +0 -188
- package/src/customTemplates/LayerToolbar.tsx +0 -580
- package/src/customTemplates/ShapeGlyph.tsx +0 -47
- package/src/customTemplates/TemplateDesigner.tsx +0 -433
- package/src/customTemplates/__tests__/library.test.ts +0 -96
- package/src/customTemplates/__tests__/normalizePositions.test.ts +0 -109
- package/src/customTemplates/__tests__/shapeDefs.test.ts +0 -49
- package/src/customTemplates/__tests__/useMemoryLayerAdapter.test.ts +0 -108
- package/src/customTemplates/designer.css +0 -732
- package/src/customTemplates/index.ts +0 -31
- package/src/customTemplates/library.ts +0 -110
- package/src/customTemplates/normalizePositions.ts +0 -75
- package/src/customTemplates/shapeDefs.ts +0 -131
- package/src/customTemplates/thumbnail.tsx +0 -63
- package/src/customTemplates/tokenDefs.ts +0 -60
- package/src/customTemplates/useDocCustomTemplates.ts +0 -52
- package/src/customTemplates/useMemoryLayerAdapter.ts +0 -129
- package/src/customThemes/CustomThemeContext.tsx +0 -185
- package/src/customThemes/CustomThemeDialog.tsx +0 -316
- package/src/customThemes/ImportThemeSection.tsx +0 -178
- package/src/customThemes/__tests__/CustomThemeContext.test.tsx +0 -64
- package/src/customThemes/__tests__/CustomThemeDialog.test.tsx +0 -47
- package/src/customThemes/__tests__/customThemeLibrary.test.ts +0 -60
- package/src/customThemes/__tests__/importThemeSection.test.tsx +0 -192
- package/src/customThemes/customThemeLibrary.ts +0 -100
- package/src/customThemes/index.ts +0 -37
- package/src/customThemes/themeControls.tsx +0 -229
- package/src/customThemes/themeDraft.ts +0 -288
- package/src/customThemes/useDocCustomThemes.ts +0 -49
- package/src/detectMarkdown.ts +0 -62
- package/src/diagram/DiagramCanvas.tsx +0 -260
- package/src/diagram/DiagramMaximizedOverlay.tsx +0 -46
- package/src/diagram/diagramCommands.ts +0 -604
- package/src/diagram/diagramConstants.ts +0 -17
- package/src/diagram/types.ts +0 -35
- package/src/editorScrollSync.ts +0 -73
- package/src/embeddedMedia.ts +0 -78
- package/src/emojiData.ts +0 -1317
- package/src/fileKind.ts +0 -158
- package/src/find/FindHighlightExtension.ts +0 -81
- package/src/find/FindToolbar.tsx +0 -314
- package/src/find/findModel.ts +0 -77
- package/src/frontmatter.ts +0 -29
- package/src/frontmatterSettings.ts +0 -23
- package/src/headingTransition.ts +0 -291
- package/src/hooks/useFileDrop.ts +0 -266
- package/src/imageEditor/CanvasSurface.tsx +0 -703
- package/src/imageEditor/ImageVersionHistoryDropdown.tsx +0 -396
- package/src/imageEditor/LayersPanel.tsx +0 -218
- package/src/imageEditor/PropertiesPanel.tsx +0 -474
- package/src/imageEditor/Toolbar.tsx +0 -459
- package/src/imageEditor/createShapeLayer.ts +0 -280
- package/src/imageEditor/icons.tsx +0 -68
- package/src/imageEditor/image-editor.css +0 -574
- package/src/imageEditor/layers/EditorImageLayer.tsx +0 -45
- package/src/imageEditor/layers/EditorShapeLayer.tsx +0 -62
- package/src/imageEditor/layers/EditorTextLayer.tsx +0 -45
- package/src/imageEditor/layers/SelectionHandles.tsx +0 -86
- package/src/imageEditor/state.ts +0 -173
- package/src/imageEditor/useImageEditor.ts +0 -385
- package/src/imageEditor/useImageEditorTokens.ts +0 -70
- package/src/index.ts +0 -559
- package/src/jsonEditor/EmbeddedRichTextField.tsx +0 -81
- package/src/jsonEditor/JsonEditor.tsx +0 -81
- package/src/jsonEditor/JsonEditorContext.tsx +0 -81
- package/src/jsonEditor/RenderNode.tsx +0 -87
- package/src/jsonEditor/editors.tsx +0 -745
- package/src/jsonEditor/index.ts +0 -2
- package/src/jsonEditor/json-editor.css +0 -463
- package/src/jsonEditor/useJsonEditorTokens.ts +0 -33
- package/src/markdownCodeFence.ts +0 -72
- package/src/mediaDragMime.ts +0 -32
- package/src/mediaEntries.ts +0 -12
- package/src/mediaReferences.ts +0 -301
- package/src/mermaid/MermaidDiagramCanvas.tsx +0 -693
- package/src/mermaid/MermaidDiagramExtension.ts +0 -243
- package/src/mermaid/MermaidDiagramTypeThumbnail.tsx +0 -184
- package/src/mermaid/MermaidDiagramWidget.tsx +0 -653
- package/src/mermaid/MermaidShapePalette.tsx +0 -245
- package/src/mermaid/__tests__/MermaidDiagramExtension.test.ts +0 -361
- package/src/mermaid/__tests__/mermaidDiagramTypes.test.ts +0 -35
- package/src/mermaid/__tests__/mermaidRenderer.test.ts +0 -49
- package/src/mermaid/__tests__/mermaidSourceOps.test.ts +0 -213
- package/src/mermaid/__tests__/mermaidSyntax.test.ts +0 -71
- package/src/mermaid/mermaidCommands.ts +0 -34
- package/src/mermaid/mermaidData.ts +0 -31
- package/src/mermaid/mermaidDiagramTypes.ts +0 -325
- package/src/mermaid/mermaidModel.ts +0 -31
- package/src/mermaid/mermaidRenderer.ts +0 -181
- package/src/mermaid/mermaidShapes.ts +0 -113
- package/src/mermaid/mermaidSourceOps.ts +0 -454
- package/src/monaco.ts +0 -35
- package/src/monacoWorkers.ts +0 -89
- package/src/outlineSource.ts +0 -171
- package/src/presentation/PresentationMode.tsx +0 -596
- package/src/rawEditorIsolation.ts +0 -18
- package/src/recorder/RecorderButton.tsx +0 -80
- package/src/recorder/RecorderModal.tsx +0 -706
- package/src/recorder/RecorderPanel.tsx +0 -77
- package/src/recorder/formats.ts +0 -159
- package/src/recorder/hooks/useMediaRecorder.ts +0 -436
- package/src/recorder/hooks/useStreamPreview.ts +0 -47
- package/src/recorder/insertMediaBlock.ts +0 -30
- package/src/recorder/sources/cameraStream.ts +0 -32
- package/src/recorder/sources/micStream.ts +0 -25
- package/src/recorder/sources/screenStream.ts +0 -162
- package/src/recorder/timingJson.ts +0 -66
- package/src/resolveBlockVisual.ts +0 -39
- package/src/scene/Scene.tsx +0 -647
- package/src/scene/SceneBlockExtension.ts +0 -205
- package/src/scene/SceneBlockToolbar.tsx +0 -216
- package/src/scene/SceneBlockWidget.tsx +0 -441
- package/src/scene/ScenePropsBar.tsx +0 -85
- package/src/scene/SceneSelection.tsx +0 -111
- package/src/scene/SceneSideToolbar.tsx +0 -89
- package/src/scene/SceneViewControls.tsx +0 -43
- package/src/scene/SceneViewport.tsx +0 -106
- package/src/scene/ShapePalette.tsx +0 -196
- package/src/scene/__tests__/DiagramAdapter.test.ts +0 -142
- package/src/scene/__tests__/SceneBlockExtension.test.ts +0 -33
- package/src/scene/__tests__/bezierEdit.test.ts +0 -85
- package/src/scene/__tests__/blockLayers.test.ts +0 -57
- package/src/scene/__tests__/fitScale.test.ts +0 -19
- package/src/scene/__tests__/sceneIsolation.test.tsx +0 -119
- package/src/scene/__tests__/shapeLayers.test.ts +0 -106
- package/src/scene/__tests__/useSceneHitTest.test.ts +0 -90
- package/src/scene/__tests__/useScenePanZoom.test.ts +0 -130
- package/src/scene/adapters/DiagramAdapter.ts +0 -79
- package/src/scene/adapters/DrawingAdapter.ts +0 -420
- package/src/scene/adapters/LayoutAdapter.ts +0 -313
- package/src/scene/adapters/blockLayers.ts +0 -159
- package/src/scene/commands/SceneCommand.ts +0 -84
- package/src/scene/commands/drawingCommands.ts +0 -318
- package/src/scene/commands/layoutCommands.ts +0 -301
- package/src/scene/fitScale.ts +0 -17
- package/src/scene/hooks/useSceneHitTest.ts +0 -105
- package/src/scene/hooks/useScenePanZoom.ts +0 -154
- package/src/scene/hooks/useSceneSelection.ts +0 -62
- package/src/scene/index.ts +0 -90
- package/src/scene/layers/DiagramEdges.tsx +0 -142
- package/src/scene/layers/edgeGeometry.ts +0 -104
- package/src/scene/layers/nodeCard.tsx +0 -164
- package/src/scene/layers/renderLayer.tsx +0 -70
- package/src/scene/layers/shapeLayers.ts +0 -201
- package/src/scene/paths/bezierEdit.ts +0 -208
- package/src/scene/scene.css +0 -874
- package/src/scene/text/SceneTextOverlay.tsx +0 -161
- package/src/scene/text/sceneTextChannel.ts +0 -46
- package/src/scene/text/sceneTextConfig.ts +0 -31
- package/src/scene/text/sceneTiptap.ts +0 -36
- package/src/scene/text/useSceneTextEditing.ts +0 -39
- package/src/scene/tools/ConnectTool.ts +0 -209
- package/src/scene/tools/DrawingConnectTool.ts +0 -231
- package/src/scene/tools/PathTool.ts +0 -158
- package/src/scene/tools/PlaceTool.ts +0 -47
- package/src/scene/tools/SceneTool.ts +0 -85
- package/src/scene/tools/SelectTool.ts +0 -300
- package/src/scene/tools/ShapeTool.ts +0 -143
- package/src/scene/tools/TextTool.ts +0 -72
- package/src/scene/tools/TokenTool.ts +0 -95
- package/src/scene/tools/createDrawShapeTool.ts +0 -82
- package/src/selectionConversions.ts +0 -155
- package/src/styles/ascii-diagram.css +0 -79
- package/src/styles/ascii-timeline.css +0 -596
- package/src/styles/code-context.css +0 -155
- package/src/styles/code-snippet.css +0 -76
- package/src/styles/diagram.css +0 -183
- package/src/styles/editor.css +0 -7131
- package/src/styles/folder-view.css +0 -210
- package/src/styles/image-edit-affordance.css +0 -201
- package/src/styles/index.css +0 -20
- package/src/styles/mermaid-diagram.css +0 -487
- package/src/styles/tree-view.css +0 -189
- package/src/teleprompter/TeleprompterControls.tsx +0 -218
- package/src/teleprompter/TeleprompterSelfView.tsx +0 -22
- package/src/teleprompter/TeleprompterSurface.tsx +0 -267
- package/src/teleprompter/TeleprompterView.tsx +0 -338
- package/src/teleprompter/canvasRenderer.ts +0 -161
- package/src/teleprompter/floatingWindow.ts +0 -352
- package/src/teleprompter/index.ts +0 -61
- package/src/teleprompter/pcmWorklet.ts +0 -62
- package/src/teleprompter/recording/insertPreamble.ts +0 -80
- package/src/teleprompter/recording/narrationSave.ts +0 -134
- package/src/teleprompter/recording/useNarrationRecorder.ts +0 -367
- package/src/teleprompter/scrollModel.ts +0 -85
- package/src/teleprompter/teleprompterTheme.ts +0 -303
- package/src/teleprompter/types.ts +0 -38
- package/src/teleprompter/useFloatingWindow.ts +0 -74
- package/src/teleprompter/useMicAnalysis.ts +0 -211
- package/src/teleprompter/useTeleprompter.ts +0 -421
- package/src/templateContentPreviewResolver.ts +0 -360
- package/src/timeline/TimelineEditorWidget.tsx +0 -861
- package/src/timeline/TimelineViewExtension.ts +0 -252
- package/src/timeline/__tests__/TimelineEditorWidget.test.tsx +0 -414
- package/src/timeline/__tests__/TimelineViewExtension.test.ts +0 -163
- package/src/timeline/__tests__/timelineCommands.test.ts +0 -359
- package/src/timeline/__tests__/timelineOps.test.ts +0 -277
- package/src/timeline/__tests__/timelinePaste.test.ts +0 -34
- package/src/timeline/timelineCommands.ts +0 -421
- package/src/timeline/timelineData.ts +0 -54
- package/src/timeline/timelineOps.ts +0 -381
- package/src/timeline/timelinePaste.ts +0 -8
- package/src/timelineSource.ts +0 -244
- package/src/tiptap/TiptapAudio.tsx +0 -86
- package/src/tiptap/TiptapVideo.tsx +0 -119
- package/src/tiptap/useResolvedMediaSrc.ts +0 -47
- package/src/tiptapBridge.ts +0 -986
- package/src/tooltipPlacement.ts +0 -13
- package/src/transformStyleId.ts +0 -17
- package/src/transitionCatalog.ts +0 -159
- package/src/treeview/TreeOutlineWidget.tsx +0 -390
- package/src/treeview/TreeViewExtension.ts +0 -250
- package/src/treeview/__tests__/TreeOutlineWidget.test.tsx +0 -156
- package/src/treeview/__tests__/TreeViewExtension.test.ts +0 -122
- package/src/treeview/__tests__/treeOps.test.ts +0 -177
- package/src/treeview/__tests__/treePaste.test.ts +0 -40
- package/src/treeview/__tests__/treeViewCommands.test.ts +0 -179
- package/src/treeview/treeOps.ts +0 -231
- package/src/treeview/treePaste.ts +0 -13
- package/src/treeview/treeViewCommands.ts +0 -99
- package/src/treeview/treeViewData.ts +0 -41
- package/src/types/monaco-shims.d.ts +0 -10
- package/src/useBlockNavigator.ts +0 -153
- package/src/useHeadingLayout.ts +0 -294
- package/src/useMonacoLoader.ts +0 -82
- package/src/useTimelineClock.ts +0 -76
- package/src/utils/collectInlineFontAwesomeCss.ts +0 -69
- package/src/utils/dropUtils.ts +0 -136
- package/src/utils/normalizeMalformedAssetUrl.ts +0 -22
- package/src/writeCanvasSettings.ts +0 -30
- package/src/wysiwygImageUpload.ts +0 -113
package/src/headingTransition.ts
DELETED
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* headingTransition
|
|
3
|
-
*
|
|
4
|
-
* Read and write a block's transition (`transition` / `transitionDirection` /
|
|
5
|
-
* `transitionDuration`) on a heading, in both editing surfaces:
|
|
6
|
-
*
|
|
7
|
-
* - Markdown (Monaco): operate on the raw heading line string.
|
|
8
|
-
* - WYSIWYG (Tiptap): operate on the heading node's `dataBlockAttrs` string
|
|
9
|
-
* (Pandoc `{…}` inner) and `dataTemplateParams` string (the params inside
|
|
10
|
-
* the squisq-native `{[…]}` annotation).
|
|
11
|
-
*
|
|
12
|
-
* The editor writes transitions to the squisq-native `{[…]}` annotation by
|
|
13
|
-
* default. It still reads legacy Pandoc `{transition=…}` attributes and
|
|
14
|
-
* removes/migrates those keys when rewriting, so the two channels cannot drift
|
|
15
|
-
* after a toolbar edit.
|
|
16
|
-
*
|
|
17
|
-
* All the brace-matching / tokenizing / serializing is delegated to the
|
|
18
|
-
* shared core helpers so this stays in lockstep with the parser by import
|
|
19
|
-
* rather than by copied regexes.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
matchTrailingTemplateAnnotation,
|
|
24
|
-
matchTrailingPandocAttr,
|
|
25
|
-
parsePandocAttrTokens,
|
|
26
|
-
serializePandocAttributes,
|
|
27
|
-
tokenizeAttrTokens,
|
|
28
|
-
splitKeyValueToken,
|
|
29
|
-
quoteAttrValue,
|
|
30
|
-
type HeadingAttributes,
|
|
31
|
-
} from '@bendyline/squisq/markdown';
|
|
32
|
-
|
|
33
|
-
/** Raw (un-coerced) transition attribute values for one block. */
|
|
34
|
-
export interface TransitionFields {
|
|
35
|
-
/** `transition` value. Empty string means "none" (`cut`). */
|
|
36
|
-
type: string;
|
|
37
|
-
/** `transitionDirection` value, or '' when unset. */
|
|
38
|
-
direction: string;
|
|
39
|
-
/** `transitionDuration` value (raw, e.g. `0.7` or `700ms`), or '' when unset. */
|
|
40
|
-
duration: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export const EMPTY_TRANSITION: TransitionFields = { type: '', direction: '', duration: '' };
|
|
44
|
-
|
|
45
|
-
/** The three keys this module owns, in canonical emit order. */
|
|
46
|
-
const TRANSITION_KEYS = ['transition', 'transitionDirection', 'transitionDuration'] as const;
|
|
47
|
-
|
|
48
|
-
const HEADING_LINE_RE = /^(#{1,6}\s+)([\s\S]*)$/;
|
|
49
|
-
|
|
50
|
-
// ============================================
|
|
51
|
-
// params map ⇄ fields
|
|
52
|
-
// ============================================
|
|
53
|
-
|
|
54
|
-
function fieldsFromParams(params: Record<string, string> | undefined): TransitionFields {
|
|
55
|
-
if (!params) return { ...EMPTY_TRANSITION };
|
|
56
|
-
return {
|
|
57
|
-
type: params.transition ?? '',
|
|
58
|
-
direction: params.transitionDirection ?? '',
|
|
59
|
-
duration: params.transitionDuration ?? '',
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Return a new params map with the transition keys rewritten from `next`,
|
|
65
|
-
* preserving every other key in its original order. When `type` is empty
|
|
66
|
-
* (none), all three transition keys are dropped; direction/duration are only
|
|
67
|
-
* written when a type is present (they're meaningless on their own).
|
|
68
|
-
*/
|
|
69
|
-
function applyFieldsToParams(
|
|
70
|
-
params: Record<string, string>,
|
|
71
|
-
next: TransitionFields,
|
|
72
|
-
): Record<string, string> {
|
|
73
|
-
const out: Record<string, string> = {};
|
|
74
|
-
for (const [key, value] of Object.entries(params)) {
|
|
75
|
-
if ((TRANSITION_KEYS as readonly string[]).includes(key)) continue;
|
|
76
|
-
out[key] = value;
|
|
77
|
-
}
|
|
78
|
-
if (next.type) {
|
|
79
|
-
out.transition = next.type;
|
|
80
|
-
if (next.direction) out.transitionDirection = next.direction;
|
|
81
|
-
if (next.duration) out.transitionDuration = next.duration;
|
|
82
|
-
}
|
|
83
|
-
return out;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function removeFieldsFromAttrs(attrs: HeadingAttributes): HeadingAttributes {
|
|
87
|
-
if (!attrs.params) return attrs;
|
|
88
|
-
const params = applyFieldsToParams(attrs.params, EMPTY_TRANSITION);
|
|
89
|
-
if (Object.keys(params).length > 0) attrs.params = params;
|
|
90
|
-
else delete attrs.params;
|
|
91
|
-
return attrs;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/** Parse a bare `key=value …` token string into a params map. */
|
|
95
|
-
function paramsFromTokenString(input: string, skipFirstToken: boolean): Record<string, string> {
|
|
96
|
-
const tokens = tokenizeAttrTokens(input);
|
|
97
|
-
const params: Record<string, string> = {};
|
|
98
|
-
for (const token of skipFirstToken ? tokens.slice(1) : tokens) {
|
|
99
|
-
const kv = splitKeyValueToken(token);
|
|
100
|
-
if (kv) params[kv.key] = kv.value;
|
|
101
|
-
}
|
|
102
|
-
return params;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function templatePartsFromInner(inner: string | null | undefined): {
|
|
106
|
-
template: string | undefined;
|
|
107
|
-
params: Record<string, string>;
|
|
108
|
-
} {
|
|
109
|
-
if (!inner) return { template: undefined, params: {} };
|
|
110
|
-
const tokens = tokenizeAttrTokens(inner);
|
|
111
|
-
const firstIsParam = tokens.length > 0 && tokens[0].indexOf('=') > 0;
|
|
112
|
-
const template = firstIsParam || tokens.length === 0 ? undefined : tokens[0];
|
|
113
|
-
const startIdx = template ? 1 : 0;
|
|
114
|
-
const params: Record<string, string> = {};
|
|
115
|
-
for (const token of tokens.slice(startIdx)) {
|
|
116
|
-
const kv = splitKeyValueToken(token);
|
|
117
|
-
if (kv) params[kv.key] = kv.value;
|
|
118
|
-
}
|
|
119
|
-
return { template, params };
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function paramsToInner(params: Record<string, string>): string | null {
|
|
123
|
-
const parts = Object.entries(params).map(([key, value]) => `${key}=${quoteAttrValue(value)}`);
|
|
124
|
-
return parts.length > 0 ? parts.join(' ') : null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function templateAnnotationOrNull(
|
|
128
|
-
template: string | undefined,
|
|
129
|
-
params: Record<string, string>,
|
|
130
|
-
): string | null {
|
|
131
|
-
const parts: string[] = [];
|
|
132
|
-
if (template) parts.push(template);
|
|
133
|
-
const paramInner = paramsToInner(params);
|
|
134
|
-
if (paramInner) parts.push(paramInner);
|
|
135
|
-
return parts.length > 0 ? `{[${parts.join(' ')}]}` : null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// ============================================
|
|
139
|
-
// Heading line (Markdown / Monaco view)
|
|
140
|
-
// ============================================
|
|
141
|
-
|
|
142
|
-
interface SplitHeadingLine {
|
|
143
|
-
/** `## ` */
|
|
144
|
-
prefix: string;
|
|
145
|
-
/** Bare heading text (trailing whitespace stripped). */
|
|
146
|
-
text: string;
|
|
147
|
-
/** Inner of the trailing Pandoc `{…}` block, or null. */
|
|
148
|
-
pandocInner: string | null;
|
|
149
|
-
/** Verbatim trailing `{[…]}` template annotation (no leading space), or ''. */
|
|
150
|
-
templateText: string;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Split a heading line into its prefix, bare text, and trailing annotation
|
|
155
|
-
* blocks. Mirrors the peel-off order in `tiptapBridge` / core's parser:
|
|
156
|
-
* the `{[…]}` template annotation sits at the very end, the Pandoc `{…}`
|
|
157
|
-
* block just before it. Returns null when `line` is not a heading.
|
|
158
|
-
*/
|
|
159
|
-
function splitHeadingLine(line: string): SplitHeadingLine | null {
|
|
160
|
-
const m = line.match(HEADING_LINE_RE);
|
|
161
|
-
if (!m) return null;
|
|
162
|
-
let rest = m[2];
|
|
163
|
-
|
|
164
|
-
let templateText = '';
|
|
165
|
-
const tm = matchTrailingTemplateAnnotation(rest);
|
|
166
|
-
if (tm) {
|
|
167
|
-
templateText = rest.slice(tm.index).trim();
|
|
168
|
-
rest = rest.slice(0, tm.index);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
let pandocInner: string | null = null;
|
|
172
|
-
const pm = matchTrailingPandocAttr(rest);
|
|
173
|
-
if (pm) {
|
|
174
|
-
pandocInner = pm.inner;
|
|
175
|
-
rest = rest.slice(0, pm.index);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return { prefix: m[1], text: rest.replace(/\s+$/, ''), pandocInner, templateText };
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Read the transition fields off a heading line. Looks in both the Pandoc
|
|
183
|
-
* `{…}` block (legacy) and the `{[…]}` template params (canonical),
|
|
184
|
-
* with the Pandoc block taking precedence. Returns the empty transition for
|
|
185
|
-
* non-heading lines.
|
|
186
|
-
*/
|
|
187
|
-
export function readHeadingLineTransition(line: string): TransitionFields {
|
|
188
|
-
const split = splitHeadingLine(line);
|
|
189
|
-
if (!split) return { ...EMPTY_TRANSITION };
|
|
190
|
-
const fromTemplate = split.templateText
|
|
191
|
-
? templatePartsFromInner(stripTemplateBraces(split.templateText)).params
|
|
192
|
-
: {};
|
|
193
|
-
const fromPandoc = split.pandocInner
|
|
194
|
-
? (parsePandocAttrTokens(split.pandocInner).params ?? {})
|
|
195
|
-
: {};
|
|
196
|
-
return fieldsFromParams({ ...fromTemplate, ...fromPandoc });
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Return `line` with its transition rewritten from `next`, writing into the
|
|
201
|
-
* squisq-native `{[…]}` annotation. Legacy Pandoc transition keys are removed
|
|
202
|
-
* while preserving ids, classes, and other Pandoc params. Non-heading lines are
|
|
203
|
-
* returned unchanged.
|
|
204
|
-
*/
|
|
205
|
-
export function setHeadingLineTransition(line: string, next: TransitionFields): string {
|
|
206
|
-
const split = splitHeadingLine(line);
|
|
207
|
-
if (!split) return line;
|
|
208
|
-
const attrs: HeadingAttributes = split.pandocInner
|
|
209
|
-
? parsePandocAttrTokens(split.pandocInner)
|
|
210
|
-
: {};
|
|
211
|
-
removeFieldsFromAttrs(attrs);
|
|
212
|
-
const pandoc = pandocBlockOrNull(attrs);
|
|
213
|
-
|
|
214
|
-
const templateParts = templatePartsFromInner(
|
|
215
|
-
split.templateText ? stripTemplateBraces(split.templateText) : null,
|
|
216
|
-
);
|
|
217
|
-
const templateParams = applyFieldsToParams(templateParts.params, next);
|
|
218
|
-
const template = templateAnnotationOrNull(templateParts.template, templateParams);
|
|
219
|
-
|
|
220
|
-
let out = split.prefix + split.text;
|
|
221
|
-
if (pandoc) out += ` ${pandoc}`;
|
|
222
|
-
if (template) out += ` ${template}`;
|
|
223
|
-
return out;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/** Strip the outer `{[` … `]}` from a verbatim template annotation. */
|
|
227
|
-
function stripTemplateBraces(templateText: string): string {
|
|
228
|
-
const m = templateText.match(/^\{\[([\s\S]*)\]\}[\s\]}]*$/);
|
|
229
|
-
return m ? m[1] : templateText;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// ============================================
|
|
233
|
-
// data-block-attrs (WYSIWYG / Tiptap view)
|
|
234
|
-
// ============================================
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Read the transition fields from a heading node's `dataBlockAttrs` (legacy
|
|
238
|
-
* Pandoc inner) plus `dataTemplateParams` (canonical `{[…]}` params). Pandoc
|
|
239
|
-
* wins so the picker mirrors the value that `markdownToDoc` will render when
|
|
240
|
-
* both channels are present.
|
|
241
|
-
*/
|
|
242
|
-
export function readBlockAttrsTransition(
|
|
243
|
-
blockAttrsInner: string | null | undefined,
|
|
244
|
-
templateParams: string | null | undefined,
|
|
245
|
-
): TransitionFields {
|
|
246
|
-
const fromTemplate = templateParams ? paramsFromTokenString(templateParams, false) : {};
|
|
247
|
-
const fromPandoc = blockAttrsInner ? (parsePandocAttrTokens(blockAttrsInner).params ?? {}) : {};
|
|
248
|
-
return fieldsFromParams({ ...fromTemplate, ...fromPandoc });
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export interface HeadingTransitionAttrs {
|
|
252
|
-
/** Inner of the Pandoc `{…}` block, without braces. */
|
|
253
|
-
blockAttrsInner: string | null;
|
|
254
|
-
/** Param string inside the `{[…]}` annotation, without the template token. */
|
|
255
|
-
templateParams: string | null;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Rewrite a heading node's transition for Tiptap, writing the transition
|
|
260
|
-
* family into `dataTemplateParams` and removing any legacy transition keys
|
|
261
|
-
* from `dataBlockAttrs`.
|
|
262
|
-
*/
|
|
263
|
-
export function setHeadingAttrsTransition(
|
|
264
|
-
blockAttrsInner: string | null | undefined,
|
|
265
|
-
templateParams: string | null | undefined,
|
|
266
|
-
next: TransitionFields,
|
|
267
|
-
): HeadingTransitionAttrs {
|
|
268
|
-
const attrs: HeadingAttributes = blockAttrsInner ? parsePandocAttrTokens(blockAttrsInner) : {};
|
|
269
|
-
removeFieldsFromAttrs(attrs);
|
|
270
|
-
const pandoc = pandocBlockOrNull(attrs);
|
|
271
|
-
|
|
272
|
-
const params = applyFieldsToParams(paramsFromTokenString(templateParams ?? '', false), next);
|
|
273
|
-
return {
|
|
274
|
-
blockAttrsInner: pandoc ? pandoc.slice(1, -1) : null,
|
|
275
|
-
templateParams: paramsToInner(params),
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// ============================================
|
|
280
|
-
// shared
|
|
281
|
-
// ============================================
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Serialize `attrs` to a `{…}` block, or null when there's nothing to emit.
|
|
285
|
-
* `serializePandocAttributes` returns the literal `{}` marker for an empty
|
|
286
|
-
* attribute set; we treat that as "no block".
|
|
287
|
-
*/
|
|
288
|
-
function pandocBlockOrNull(attrs: HeadingAttributes): string | null {
|
|
289
|
-
const raw = serializePandocAttributes(attrs);
|
|
290
|
-
return raw == null || raw === '{}' ? null : raw;
|
|
291
|
-
}
|
package/src/hooks/useFileDrop.ts
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useFileDrop
|
|
3
|
-
*
|
|
4
|
-
* React hook that manages HTML5 drag-and-drop state for file uploads.
|
|
5
|
-
* Tracks whether files are being dragged over the target element,
|
|
6
|
-
* classifies dragged file types (media vs text), and dispatches
|
|
7
|
-
* drop events to callers.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
11
|
-
|
|
12
|
-
// ─── File classification ────────────────────────────────
|
|
13
|
-
|
|
14
|
-
const MEDIA_EXTENSIONS = new Set([
|
|
15
|
-
'png',
|
|
16
|
-
'jpg',
|
|
17
|
-
'jpeg',
|
|
18
|
-
'gif',
|
|
19
|
-
'webp',
|
|
20
|
-
'svg',
|
|
21
|
-
'avif',
|
|
22
|
-
'ico',
|
|
23
|
-
'mp4',
|
|
24
|
-
'webm',
|
|
25
|
-
'mov',
|
|
26
|
-
'avi',
|
|
27
|
-
'mp3',
|
|
28
|
-
'wav',
|
|
29
|
-
'ogg',
|
|
30
|
-
'aac',
|
|
31
|
-
'm4a',
|
|
32
|
-
'flac',
|
|
33
|
-
]);
|
|
34
|
-
|
|
35
|
-
const TEXT_EXTENSIONS = new Set(['md', 'txt', 'docx']);
|
|
36
|
-
|
|
37
|
-
export type FileCategory = 'media' | 'text' | 'unknown';
|
|
38
|
-
export type DragContentType = 'media' | 'text' | 'mixed' | null;
|
|
39
|
-
export type DropTarget = 'media' | 'insert' | 'replace';
|
|
40
|
-
|
|
41
|
-
function extensionOf(name: string): string {
|
|
42
|
-
const dot = name.lastIndexOf('.');
|
|
43
|
-
return dot >= 0 ? name.slice(dot + 1).toLowerCase() : '';
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function classifyFile(file: { name: string; type: string }): FileCategory {
|
|
47
|
-
const ext = extensionOf(file.name);
|
|
48
|
-
if (MEDIA_EXTENSIONS.has(ext)) return 'media';
|
|
49
|
-
if (TEXT_EXTENSIONS.has(ext)) return 'text';
|
|
50
|
-
|
|
51
|
-
// Fallback to MIME type
|
|
52
|
-
if (
|
|
53
|
-
file.type.startsWith('image/') ||
|
|
54
|
-
file.type.startsWith('video/') ||
|
|
55
|
-
file.type.startsWith('audio/')
|
|
56
|
-
) {
|
|
57
|
-
return 'media';
|
|
58
|
-
}
|
|
59
|
-
if (file.type === 'text/plain' || file.type === 'text/markdown') {
|
|
60
|
-
return 'text';
|
|
61
|
-
}
|
|
62
|
-
return 'unknown';
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Classify dragged items from a DataTransfer during dragenter/dragover.
|
|
67
|
-
* Browsers restrict full file access during drag — only MIME types are
|
|
68
|
-
* available via DataTransferItem.type.
|
|
69
|
-
*/
|
|
70
|
-
function classifyDataTransferItems(items: DataTransferItemList): DragContentType {
|
|
71
|
-
let hasMedia = false;
|
|
72
|
-
let hasText = false;
|
|
73
|
-
|
|
74
|
-
for (let i = 0; i < items.length; i++) {
|
|
75
|
-
const item = items[i];
|
|
76
|
-
if (item.kind !== 'file') continue;
|
|
77
|
-
|
|
78
|
-
const mime = item.type.toLowerCase();
|
|
79
|
-
if (mime.startsWith('image/') || mime.startsWith('video/') || mime.startsWith('audio/')) {
|
|
80
|
-
hasMedia = true;
|
|
81
|
-
} else if (
|
|
82
|
-
mime === 'text/plain' ||
|
|
83
|
-
mime === 'text/markdown' ||
|
|
84
|
-
mime === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
|
85
|
-
) {
|
|
86
|
-
hasText = true;
|
|
87
|
-
} else {
|
|
88
|
-
// Unknown MIME — browsers often report '' for many file types during drag.
|
|
89
|
-
// We can't classify, so assume mixed to show all drop zones.
|
|
90
|
-
hasMedia = true;
|
|
91
|
-
hasText = true;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (hasMedia && hasText) return 'mixed';
|
|
96
|
-
if (hasMedia) return 'media';
|
|
97
|
-
if (hasText) return 'text';
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ─── Hook ────────────────────────────────────────────────
|
|
102
|
-
|
|
103
|
-
export interface UseFileDropOptions {
|
|
104
|
-
/** Called when files are dropped on a specific target zone. */
|
|
105
|
-
onDrop: (files: File[], target: DropTarget) => void;
|
|
106
|
-
/** Whether drop is enabled (default: true) */
|
|
107
|
-
enabled?: boolean;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export interface UseFileDropResult {
|
|
111
|
-
/** Whether a drag-with-files is currently hovering over the container */
|
|
112
|
-
isDragging: boolean;
|
|
113
|
-
/** Classification of the dragged content */
|
|
114
|
-
dragContentType: DragContentType;
|
|
115
|
-
/** Attach these to the container element */
|
|
116
|
-
containerProps: {
|
|
117
|
-
onDragEnter: (e: React.DragEvent) => void;
|
|
118
|
-
onDragOver: (e: React.DragEvent) => void;
|
|
119
|
-
onDragLeave: (e: React.DragEvent) => void;
|
|
120
|
-
onDrop: (e: React.DragEvent) => void;
|
|
121
|
-
};
|
|
122
|
-
/** Create props for an individual drop zone target */
|
|
123
|
-
zoneProps: (target: DropTarget) => {
|
|
124
|
-
onDragOver: (e: React.DragEvent) => void;
|
|
125
|
-
onDrop: (e: React.DragEvent) => void;
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function useFileDrop({ onDrop, enabled = true }: UseFileDropOptions): UseFileDropResult {
|
|
130
|
-
const [isDragging, setIsDragging] = useState(false);
|
|
131
|
-
const [dragContentType, setDragContentType] = useState<DragContentType>(null);
|
|
132
|
-
|
|
133
|
-
// Counter-based tracking: dragenter/dragleave fire on child elements,
|
|
134
|
-
// so we track a count rather than a boolean.
|
|
135
|
-
const dragCounterRef = useRef(0);
|
|
136
|
-
|
|
137
|
-
// True while a drag that originated *inside* this page is in flight.
|
|
138
|
-
// Browsers expose draggable `<img>` elements as virtual files in
|
|
139
|
-
// `dataTransfer.types` (so they can be dropped onto the desktop), so
|
|
140
|
-
// checking for `'Files'` alone can't tell an OS file drop apart from
|
|
141
|
-
// an in-app image reorder. We watch the document-level `dragstart`
|
|
142
|
-
// event — only OS drags from outside the page lack a `dragstart` —
|
|
143
|
-
// and bail out of the overlay logic when this flag is set.
|
|
144
|
-
const inPageDragRef = useRef(false);
|
|
145
|
-
useEffect(() => {
|
|
146
|
-
if (!enabled) return;
|
|
147
|
-
const onStart = () => {
|
|
148
|
-
inPageDragRef.current = true;
|
|
149
|
-
};
|
|
150
|
-
const onEnd = () => {
|
|
151
|
-
inPageDragRef.current = false;
|
|
152
|
-
};
|
|
153
|
-
document.addEventListener('dragstart', onStart, true);
|
|
154
|
-
document.addEventListener('dragend', onEnd, true);
|
|
155
|
-
document.addEventListener('drop', onEnd, true);
|
|
156
|
-
return () => {
|
|
157
|
-
document.removeEventListener('dragstart', onStart, true);
|
|
158
|
-
document.removeEventListener('dragend', onEnd, true);
|
|
159
|
-
document.removeEventListener('drop', onEnd, true);
|
|
160
|
-
};
|
|
161
|
-
}, [enabled]);
|
|
162
|
-
|
|
163
|
-
const handleDragEnter = useCallback(
|
|
164
|
-
(e: React.DragEvent) => {
|
|
165
|
-
if (!enabled) return;
|
|
166
|
-
|
|
167
|
-
// Drag started inside the page (e.g. repositioning an `<img>`
|
|
168
|
-
// already in the WYSIWYG document, or dragging a thumbnail out of
|
|
169
|
-
// the MediaBin). Do NOT show the file-drop overlay — let
|
|
170
|
-
// ProseMirror handle the in-document move with its dropcursor.
|
|
171
|
-
if (inPageDragRef.current) return;
|
|
172
|
-
|
|
173
|
-
// For OS-level drags, the browser sets the special `'Files'`
|
|
174
|
-
// type. Bail out for anything else (text drags between apps,
|
|
175
|
-
// etc.) so we don't flash the overlay on irrelevant gestures.
|
|
176
|
-
const types = e.dataTransfer.types;
|
|
177
|
-
const hasFiles = types && Array.from(types).includes('Files');
|
|
178
|
-
if (!hasFiles) return;
|
|
179
|
-
|
|
180
|
-
const classification = e.dataTransfer.items
|
|
181
|
-
? classifyDataTransferItems(e.dataTransfer.items)
|
|
182
|
-
: 'mixed';
|
|
183
|
-
if (!classification) return;
|
|
184
|
-
|
|
185
|
-
e.preventDefault();
|
|
186
|
-
dragCounterRef.current++;
|
|
187
|
-
|
|
188
|
-
if (dragCounterRef.current === 1) {
|
|
189
|
-
setIsDragging(true);
|
|
190
|
-
setDragContentType(classification);
|
|
191
|
-
}
|
|
192
|
-
},
|
|
193
|
-
[enabled],
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
const handleDragOver = useCallback(
|
|
197
|
-
(e: React.DragEvent) => {
|
|
198
|
-
if (!enabled) return;
|
|
199
|
-
e.preventDefault();
|
|
200
|
-
// Required to allow drop
|
|
201
|
-
e.dataTransfer.dropEffect = 'copy';
|
|
202
|
-
},
|
|
203
|
-
[enabled],
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
const handleDragLeave = useCallback(
|
|
207
|
-
(e: React.DragEvent) => {
|
|
208
|
-
if (!enabled) return;
|
|
209
|
-
e.preventDefault();
|
|
210
|
-
dragCounterRef.current = Math.max(0, dragCounterRef.current - 1);
|
|
211
|
-
|
|
212
|
-
if (dragCounterRef.current === 0) {
|
|
213
|
-
setIsDragging(false);
|
|
214
|
-
setDragContentType(null);
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
[enabled],
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
const handleDrop = useCallback(
|
|
221
|
-
(e: React.DragEvent) => {
|
|
222
|
-
if (!enabled) return;
|
|
223
|
-
e.preventDefault();
|
|
224
|
-
dragCounterRef.current = 0;
|
|
225
|
-
setIsDragging(false);
|
|
226
|
-
setDragContentType(null);
|
|
227
|
-
// Actual file handling is done by zone-specific onDrop
|
|
228
|
-
},
|
|
229
|
-
[enabled],
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
const zoneProps = useCallback(
|
|
233
|
-
(target: DropTarget) => ({
|
|
234
|
-
onDragOver: (e: React.DragEvent) => {
|
|
235
|
-
e.preventDefault();
|
|
236
|
-
e.stopPropagation();
|
|
237
|
-
e.dataTransfer.dropEffect = 'copy';
|
|
238
|
-
},
|
|
239
|
-
onDrop: (e: React.DragEvent) => {
|
|
240
|
-
e.preventDefault();
|
|
241
|
-
e.stopPropagation();
|
|
242
|
-
dragCounterRef.current = 0;
|
|
243
|
-
setIsDragging(false);
|
|
244
|
-
setDragContentType(null);
|
|
245
|
-
|
|
246
|
-
const files = Array.from(e.dataTransfer.files);
|
|
247
|
-
if (files.length > 0) {
|
|
248
|
-
onDrop(files, target);
|
|
249
|
-
}
|
|
250
|
-
},
|
|
251
|
-
}),
|
|
252
|
-
[onDrop],
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
return {
|
|
256
|
-
isDragging,
|
|
257
|
-
dragContentType,
|
|
258
|
-
containerProps: {
|
|
259
|
-
onDragEnter: handleDragEnter,
|
|
260
|
-
onDragOver: handleDragOver,
|
|
261
|
-
onDragLeave: handleDragLeave,
|
|
262
|
-
onDrop: handleDrop,
|
|
263
|
-
},
|
|
264
|
-
zoneProps,
|
|
265
|
-
};
|
|
266
|
-
}
|