@r2digisolutions/components 0.1.7 → 0.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/dist/components/atoms/IconButton/IconButton.svelte +1 -1
- package/dist/components/atoms/MediaKindIcon/MediaKindIcon.stories.js +8 -0
- package/dist/components/atoms/MediaKindIcon/MediaKindIcon.svelte +122 -0
- package/dist/components/atoms/MediaKindIcon/MediaKindIcon.svelte.d.ts +11 -0
- package/dist/components/atoms/MediaKindIcon/MediaKindIconStory.svelte +12 -0
- package/dist/components/atoms/MediaKindIcon/MediaKindIconStory.svelte.d.ts +18 -0
- package/dist/components/atoms/PanKnob/PanKnob.stories.d.ts +9 -0
- package/dist/components/atoms/PanKnob/PanKnob.stories.js +8 -0
- package/dist/components/atoms/PanKnob/PanKnob.svelte +218 -0
- package/dist/components/atoms/PanKnob/PanKnob.svelte.d.ts +19 -0
- package/dist/components/atoms/PanKnob/PanKnobStory.svelte +15 -0
- package/dist/components/atoms/PanKnob/PanKnobStory.svelte.d.ts +3 -0
- package/dist/components/atoms/Playhead/Playhead.stories.js +8 -0
- package/dist/components/atoms/Playhead/Playhead.svelte +98 -0
- package/dist/components/atoms/Playhead/Playhead.svelte.d.ts +21 -0
- package/dist/components/atoms/Playhead/PlayheadStory.svelte +9 -0
- package/dist/components/atoms/Playhead/PlayheadStory.svelte.d.ts +18 -0
- package/dist/components/atoms/TimeRuler/TimeRuler.stories.js +8 -0
- package/dist/components/atoms/TimeRuler/TimeRuler.svelte +117 -0
- package/dist/components/atoms/TimeRuler/TimeRuler.svelte.d.ts +17 -0
- package/dist/components/atoms/TimeRuler/TimeRulerStory.svelte +7 -0
- package/dist/components/atoms/TimeRuler/TimeRulerStory.svelte.d.ts +18 -0
- package/dist/components/atoms/TimelineGrid/TimelineGrid.stories.js +8 -0
- package/dist/components/atoms/TimelineGrid/TimelineGrid.svelte +39 -0
- package/dist/components/atoms/TimelineGrid/TimelineGrid.svelte.d.ts +11 -0
- package/dist/components/atoms/TimelineGrid/TimelineGridStory.svelte +7 -0
- package/dist/components/atoms/TimelineGrid/TimelineGridStory.svelte.d.ts +18 -0
- package/dist/components/atoms/Tooltip/Tooltip.svelte +1 -1
- package/dist/components/atoms/TrimHandle/TrimHandle.stories.js +8 -0
- package/dist/components/atoms/TrimHandle/TrimHandle.svelte +63 -0
- package/dist/components/atoms/TrimHandle/TrimHandle.svelte.d.ts +12 -0
- package/dist/components/atoms/TrimHandle/TrimHandleStory.svelte +11 -0
- package/dist/components/atoms/TrimHandle/TrimHandleStory.svelte.d.ts +18 -0
- package/dist/components/molecules/AiAssistPanel/AiAssistPanel.stories.d.ts +9 -0
- package/dist/components/molecules/AiAssistPanel/AiAssistPanel.stories.js +8 -0
- package/dist/components/molecules/AiAssistPanel/AiAssistPanel.svelte +102 -0
- package/dist/components/molecules/AiAssistPanel/AiAssistPanel.svelte.d.ts +20 -0
- package/dist/components/molecules/AiAssistPanel/AiAssistPanelStory.svelte +34 -0
- package/dist/components/molecules/AiAssistPanel/AiAssistPanelStory.svelte.d.ts +3 -0
- package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte +97 -61
- package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte.d.ts +2 -0
- package/dist/components/molecules/BulkEditPanel/BulkEditPanel.stories.js +8 -0
- package/dist/components/molecules/BulkEditPanel/BulkEditPanel.svelte +117 -0
- package/dist/components/molecules/BulkEditPanel/BulkEditPanel.svelte.d.ts +23 -0
- package/dist/components/molecules/BulkEditPanel/BulkEditPanelStory.svelte +18 -0
- package/dist/components/molecules/BulkEditPanel/BulkEditPanelStory.svelte.d.ts +18 -0
- package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.stories.js +8 -0
- package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.svelte +858 -0
- package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.svelte.d.ts +43 -0
- package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanelStory.svelte +7 -0
- package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanelStory.svelte.d.ts +18 -0
- package/dist/components/molecules/CanvasInspector/CanvasInspector.stories.d.ts +9 -0
- package/dist/components/molecules/CanvasInspector/CanvasInspector.stories.js +8 -0
- package/dist/components/molecules/CanvasInspector/CanvasInspector.svelte +1140 -0
- package/dist/components/molecules/CanvasInspector/CanvasInspector.svelte.d.ts +28 -0
- package/dist/components/molecules/CanvasInspector/CanvasInspectorStory.svelte +20 -0
- package/dist/components/molecules/CanvasInspector/CanvasInspectorStory.svelte.d.ts +3 -0
- package/dist/components/molecules/ColorPicker/ColorPicker.svelte +46 -5
- package/dist/components/molecules/ColorPicker/ColorPicker.svelte.d.ts +2 -0
- package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.stories.d.ts +9 -0
- package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.stories.js +8 -0
- package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.svelte +108 -0
- package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.svelte.d.ts +18 -0
- package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenuStory.svelte +15 -0
- package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenuStory.svelte.d.ts +3 -0
- package/dist/components/molecules/ConflictResolver/ConflictResolver.stories.js +8 -0
- package/dist/components/molecules/ConflictResolver/ConflictResolver.svelte +73 -0
- package/dist/components/molecules/ConflictResolver/ConflictResolver.svelte.d.ts +16 -0
- package/dist/components/molecules/ConflictResolver/ConflictResolverStory.svelte +11 -0
- package/dist/components/molecules/ConflictResolver/ConflictResolverStory.svelte.d.ts +18 -0
- package/dist/components/molecules/ContextMenu/ContextMenu.svelte +237 -66
- package/dist/components/molecules/ContextMenu/ContextMenu.svelte.d.ts +9 -0
- package/dist/components/molecules/ExpressionEditor/ExpressionEditor.stories.d.ts +9 -0
- package/dist/components/molecules/ExpressionEditor/ExpressionEditor.stories.js +8 -0
- package/dist/components/molecules/ExpressionEditor/ExpressionEditor.svelte +56 -0
- package/dist/components/molecules/ExpressionEditor/ExpressionEditor.svelte.d.ts +12 -0
- package/dist/components/molecules/ExpressionEditor/ExpressionEditorStory.svelte +12 -0
- package/dist/components/molecules/ExpressionEditor/ExpressionEditorStory.svelte.d.ts +3 -0
- package/dist/components/molecules/FilterList/FilterList.stories.d.ts +9 -0
- package/dist/components/molecules/FilterList/FilterList.stories.js +8 -0
- package/dist/components/molecules/FilterList/FilterList.svelte +101 -0
- package/dist/components/molecules/FilterList/FilterList.svelte.d.ts +18 -0
- package/dist/components/molecules/FilterList/FilterListStory.svelte +31 -0
- package/dist/components/molecules/FilterList/FilterListStory.svelte.d.ts +3 -0
- package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.stories.d.ts +9 -0
- package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.stories.js +8 -0
- package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte +109 -0
- package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte.d.ts +20 -0
- package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowserStory.svelte +18 -0
- package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowserStory.svelte.d.ts +3 -0
- package/dist/components/molecules/MediaAssetCard/MediaAssetCard.stories.js +8 -0
- package/dist/components/molecules/MediaAssetCard/MediaAssetCard.svelte +50 -0
- package/dist/components/molecules/MediaAssetCard/MediaAssetCard.svelte.d.ts +11 -0
- package/dist/components/molecules/MediaAssetCard/MediaAssetCardStory.svelte +13 -0
- package/dist/components/molecules/MediaAssetCard/MediaAssetCardStory.svelte.d.ts +18 -0
- package/dist/components/molecules/MediaLayerItem/MediaLayerItem.stories.js +8 -0
- package/dist/components/molecules/MediaLayerItem/MediaLayerItem.svelte +380 -0
- package/dist/components/molecules/MediaLayerItem/MediaLayerItem.svelte.d.ts +33 -0
- package/dist/components/molecules/MediaLayerItem/MediaLayerItemStory.svelte +14 -0
- package/dist/components/molecules/MediaLayerItem/MediaLayerItemStory.svelte.d.ts +18 -0
- package/dist/components/molecules/MediaLayerList/MediaLayerList.stories.d.ts +9 -0
- package/dist/components/molecules/MediaLayerList/MediaLayerList.stories.js +8 -0
- package/dist/components/molecules/MediaLayerList/MediaLayerList.svelte +399 -0
- package/dist/components/molecules/MediaLayerList/MediaLayerList.svelte.d.ts +37 -0
- package/dist/components/molecules/MediaLayerList/MediaLayerListStory.svelte +24 -0
- package/dist/components/molecules/MediaLayerList/MediaLayerListStory.svelte.d.ts +3 -0
- package/dist/components/molecules/MediaStage/MediaStage.stories.d.ts +9 -0
- package/dist/components/molecules/MediaStage/MediaStage.stories.js +8 -0
- package/dist/components/molecules/MediaStage/MediaStage.svelte +1498 -0
- package/dist/components/molecules/MediaStage/MediaStage.svelte.d.ts +45 -0
- package/dist/components/molecules/MediaStage/MediaStageStory.svelte +35 -0
- package/dist/components/molecules/MediaStage/MediaStageStory.svelte.d.ts +3 -0
- package/dist/components/molecules/MediaTimeline/MediaTimeline.stories.d.ts +9 -0
- package/dist/components/molecules/MediaTimeline/MediaTimeline.stories.js +8 -0
- package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte +441 -0
- package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte.d.ts +39 -0
- package/dist/components/molecules/MediaTimeline/MediaTimelineStory.svelte +20 -0
- package/dist/components/molecules/MediaTimeline/MediaTimelineStory.svelte.d.ts +3 -0
- package/dist/components/molecules/MixerChannel/MixerChannel.stories.d.ts +9 -0
- package/dist/components/molecules/MixerChannel/MixerChannel.stories.js +8 -0
- package/dist/components/molecules/MixerChannel/MixerChannel.svelte +92 -0
- package/dist/components/molecules/MixerChannel/MixerChannel.svelte.d.ts +11 -0
- package/dist/components/molecules/MixerChannel/MixerChannelStory.svelte +13 -0
- package/dist/components/molecules/MixerChannel/MixerChannelStory.svelte.d.ts +3 -0
- package/dist/components/molecules/NodeGraph/GraphBlueprintNode.svelte +454 -0
- package/dist/components/molecules/NodeGraph/GraphBlueprintNode.svelte.d.ts +8 -0
- package/dist/components/molecules/NodeGraph/GraphFlowBridge.svelte +26 -0
- package/dist/components/molecules/NodeGraph/GraphFlowBridge.svelte.d.ts +22 -0
- package/dist/components/molecules/NodeGraph/NodeGraph.stories.d.ts +12 -0
- package/dist/components/molecules/NodeGraph/NodeGraph.stories.js +9 -0
- package/dist/components/molecules/NodeGraph/NodeGraph.svelte +1409 -0
- package/dist/components/molecules/NodeGraph/NodeGraph.svelte.d.ts +33 -0
- package/dist/components/molecules/NodeGraph/NodeGraphStory.svelte +90 -0
- package/dist/components/molecules/NodeGraph/NodeGraphStory.svelte.d.ts +3 -0
- package/dist/components/molecules/NodePalette/NodePalette.stories.js +8 -0
- package/dist/components/molecules/NodePalette/NodePalette.svelte +86 -0
- package/dist/components/molecules/NodePalette/NodePalette.svelte.d.ts +11 -0
- package/dist/components/molecules/NodePalette/NodePaletteStory.svelte +11 -0
- package/dist/components/molecules/NodePalette/NodePaletteStory.svelte.d.ts +18 -0
- package/dist/components/molecules/PdfViewer/PdfViewer.svelte.d.ts +1 -1
- package/dist/components/molecules/Poll/Poll.stories.d.ts +1 -1
- package/dist/components/molecules/ProgramMonitor/ProgramMonitor.stories.js +8 -0
- package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte +794 -0
- package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte.d.ts +25 -0
- package/dist/components/molecules/ProgramMonitor/ProgramMonitorStory.svelte +16 -0
- package/dist/components/molecules/ProgramMonitor/ProgramMonitorStory.svelte.d.ts +18 -0
- package/dist/components/molecules/PropertyField/PropertyField.svelte +57 -3
- package/dist/components/molecules/PropertyField/PropertyField.svelte.d.ts +10 -0
- package/dist/components/molecules/PropertyField/PropertyFieldStory.svelte +21 -0
- package/dist/components/molecules/PropertyGroup/PropertyGroup.svelte +1 -1
- package/dist/components/molecules/QueryBuilder/QueryBuilder.stories.d.ts +9 -0
- package/dist/components/molecules/QueryBuilder/QueryBuilder.stories.js +8 -0
- package/dist/components/molecules/QueryBuilder/QueryBuilder.svelte +52 -0
- package/dist/components/molecules/QueryBuilder/QueryBuilder.svelte.d.ts +18 -0
- package/dist/components/molecules/QueryBuilder/QueryBuilderStory.svelte +62 -0
- package/dist/components/molecules/QueryBuilder/QueryBuilderStory.svelte.d.ts +3 -0
- package/dist/components/molecules/RelationPicker/RelationPicker.stories.d.ts +9 -0
- package/dist/components/molecules/RelationPicker/RelationPicker.stories.js +8 -0
- package/dist/components/molecules/RelationPicker/RelationPicker.svelte +180 -0
- package/dist/components/molecules/RelationPicker/RelationPicker.svelte.d.ts +24 -0
- package/dist/components/molecules/RelationPicker/RelationPickerStory.svelte +16 -0
- package/dist/components/molecules/RelationPicker/RelationPickerStory.svelte.d.ts +3 -0
- package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.stories.d.ts +9 -0
- package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.stories.js +8 -0
- package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.svelte +154 -0
- package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.svelte.d.ts +12 -0
- package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilderStory.svelte +16 -0
- package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilderStory.svelte.d.ts +3 -0
- package/dist/components/molecules/SecretField/SecretField.stories.d.ts +9 -0
- package/dist/components/molecules/SecretField/SecretField.stories.js +8 -0
- package/dist/components/molecules/SecretField/SecretField.svelte +58 -0
- package/dist/components/molecules/SecretField/SecretField.svelte.d.ts +15 -0
- package/dist/components/molecules/SecretField/SecretFieldStory.svelte +8 -0
- package/dist/components/molecules/SecretField/SecretFieldStory.svelte.d.ts +3 -0
- package/dist/components/molecules/SplitPane/SplitPane.svelte +99 -40
- package/dist/components/molecules/SplitPane/SplitPane.svelte.d.ts +10 -2
- package/dist/components/molecules/TableToolbar/TableToolbar.svelte.d.ts +1 -1
- package/dist/components/molecules/Terminal/Terminal.stories.js +20 -0
- package/dist/components/molecules/Terminal/Terminal.svelte +238 -0
- package/dist/components/molecules/Terminal/Terminal.svelte.d.ts +19 -0
- package/dist/components/molecules/Terminal/TerminalStory.svelte +47 -0
- package/dist/components/molecules/Terminal/TerminalStory.svelte.d.ts +6 -0
- package/dist/components/molecules/TimelineClip/TimelineClip.stories.js +8 -0
- package/dist/components/molecules/TimelineClip/TimelineClip.svelte +193 -0
- package/dist/components/molecules/TimelineClip/TimelineClip.svelte.d.ts +18 -0
- package/dist/components/molecules/TimelineClip/TimelineClipStory.svelte +18 -0
- package/dist/components/molecules/TimelineClip/TimelineClipStory.svelte.d.ts +18 -0
- package/dist/components/molecules/TimelineTrack/TimelineTrack.stories.js +8 -0
- package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte +126 -0
- package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte.d.ts +27 -0
- package/dist/components/molecules/TimelineTrack/TimelineTrackStory.svelte +35 -0
- package/dist/components/molecules/TimelineTrack/TimelineTrackStory.svelte.d.ts +18 -0
- package/dist/components/molecules/TraceWaterfall/TraceWaterfall.stories.js +8 -0
- package/dist/components/molecules/TraceWaterfall/TraceWaterfall.svelte +158 -0
- package/dist/components/molecules/TraceWaterfall/TraceWaterfall.svelte.d.ts +18 -0
- package/dist/components/molecules/TraceWaterfall/TraceWaterfallStory.svelte +55 -0
- package/dist/components/molecules/TraceWaterfall/TraceWaterfallStory.svelte.d.ts +18 -0
- package/dist/components/molecules/TrackHeader/TrackHeader.stories.d.ts +9 -0
- package/dist/components/molecules/TrackHeader/TrackHeader.stories.js +8 -0
- package/dist/components/molecules/TrackHeader/TrackHeader.svelte +54 -0
- package/dist/components/molecules/TrackHeader/TrackHeader.svelte.d.ts +9 -0
- package/dist/components/molecules/TrackHeader/TrackHeaderStory.svelte +10 -0
- package/dist/components/molecules/TrackHeader/TrackHeaderStory.svelte.d.ts +3 -0
- package/dist/components/molecules/TransportControls/TransportControls.stories.d.ts +9 -0
- package/dist/components/molecules/TransportControls/TransportControls.stories.js +8 -0
- package/dist/components/molecules/TransportControls/TransportControls.svelte +135 -0
- package/dist/components/molecules/TransportControls/TransportControls.svelte.d.ts +24 -0
- package/dist/components/molecules/TransportControls/TransportControlsStory.svelte +40 -0
- package/dist/components/molecules/TransportControls/TransportControlsStory.svelte.d.ts +3 -0
- package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.stories.js +8 -0
- package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.svelte +117 -0
- package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.svelte.d.ts +20 -0
- package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanelStory.svelte +36 -0
- package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanelStory.svelte.d.ts +18 -0
- package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.stories.js +8 -0
- package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.svelte +213 -0
- package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.svelte.d.ts +22 -0
- package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanelStory.svelte +7 -0
- package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanelStory.svelte.d.ts +18 -0
- package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.stories.js +8 -0
- package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.svelte +524 -0
- package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.svelte.d.ts +32 -0
- package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanelStory.svelte +7 -0
- package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanelStory.svelte.d.ts +18 -0
- package/dist/components/molecules/VideoPlayer/VideoPlayer.stories.d.ts +1 -1
- package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.stories.d.ts +9 -0
- package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.stories.js +8 -0
- package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte +112 -0
- package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte.d.ts +15 -0
- package/dist/components/molecules/VideoTrackHeader/VideoTrackHeaderStory.svelte +10 -0
- package/dist/components/molecules/VideoTrackHeader/VideoTrackHeaderStory.svelte.d.ts +3 -0
- package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.stories.js +8 -0
- package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.svelte +113 -0
- package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.svelte.d.ts +18 -0
- package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanelStory.svelte +7 -0
- package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanelStory.svelte.d.ts +18 -0
- package/dist/components/molecules/WaveformRegion/WaveformRegion.stories.js +8 -0
- package/dist/components/molecules/WaveformRegion/WaveformRegion.svelte +82 -0
- package/dist/components/molecules/WaveformRegion/WaveformRegion.svelte.d.ts +13 -0
- package/dist/components/molecules/WaveformRegion/WaveformRegionStory.svelte +17 -0
- package/dist/components/molecules/WaveformRegion/WaveformRegionStory.svelte.d.ts +18 -0
- package/dist/components/molecules/WidgetCanvas/WidgetCanvas.svelte +13 -4
- package/dist/components/molecules/WidgetCanvas/WidgetCanvas.svelte.d.ts +3 -1
- package/dist/components/molecules/WidgetCanvas/widgetCanvasContext.d.ts +2 -0
- package/dist/components/molecules/WidgetFrame/WidgetFrame.svelte +206 -37
- package/dist/components/molecules/WidgetFrame/WidgetFrame.svelte.d.ts +31 -0
- package/dist/components/organisms/AudioEditor/AudioEditor.stories.d.ts +12 -0
- package/dist/components/organisms/AudioEditor/AudioEditor.stories.js +9 -0
- package/dist/components/organisms/AudioEditor/AudioEditor.svelte +324 -0
- package/dist/components/organisms/AudioEditor/AudioEditor.svelte.d.ts +13 -0
- package/dist/components/organisms/AudioEditor/AudioEditorStory.svelte +10 -0
- package/dist/components/organisms/AudioEditor/AudioEditorStory.svelte.d.ts +3 -0
- package/dist/components/organisms/BlogEditor/BlogEditor.stories.d.ts +12 -0
- package/dist/components/organisms/BlogEditor/BlogEditor.stories.js +9 -0
- package/dist/components/organisms/BlogEditor/BlogEditor.svelte +1208 -0
- package/dist/components/organisms/BlogEditor/BlogEditor.svelte.d.ts +16 -0
- package/dist/components/organisms/BlogEditor/BlogEditorStory.svelte +144 -0
- package/dist/components/organisms/BlogEditor/BlogEditorStory.svelte.d.ts +3 -0
- package/dist/components/organisms/BlogEditor/DemoBlogCard.svelte +28 -0
- package/dist/components/organisms/BlogEditor/DemoBlogCard.svelte.d.ts +10 -0
- package/dist/components/organisms/BlogEditor/DemoBlogStats.svelte +34 -0
- package/dist/components/organisms/BlogEditor/DemoBlogStats.svelte.d.ts +11 -0
- package/dist/components/organisms/BlogEditor/DemoBlogWidget.svelte +13 -0
- package/dist/components/organisms/BlogEditor/DemoBlogWidget.svelte.d.ts +8 -0
- package/dist/components/organisms/BlogRenderer/BlogRenderer.stories.js +8 -0
- package/dist/components/organisms/BlogRenderer/BlogRenderer.svelte +469 -0
- package/dist/components/organisms/BlogRenderer/BlogRenderer.svelte.d.ts +14 -0
- package/dist/components/organisms/BlogRenderer/BlogRendererStory.svelte +20 -0
- package/dist/components/organisms/BlogRenderer/BlogRendererStory.svelte.d.ts +18 -0
- package/dist/components/organisms/BlueprintEditor/BlueprintEditor.stories.d.ts +12 -0
- package/dist/components/organisms/BlueprintEditor/BlueprintEditor.stories.js +9 -0
- package/dist/components/organisms/BlueprintEditor/BlueprintEditor.svelte +1012 -0
- package/dist/components/organisms/BlueprintEditor/BlueprintEditor.svelte.d.ts +16 -0
- package/dist/components/organisms/BlueprintEditor/BlueprintEditorStory.svelte +76 -0
- package/dist/components/organisms/BlueprintEditor/BlueprintEditorStory.svelte.d.ts +3 -0
- package/dist/components/organisms/CanvasEditor/CanvasEditor.stories.d.ts +12 -0
- package/dist/components/organisms/CanvasEditor/CanvasEditor.stories.js +9 -0
- package/dist/components/organisms/CanvasEditor/CanvasEditor.svelte +1680 -0
- package/dist/components/organisms/CanvasEditor/CanvasEditor.svelte.d.ts +18 -0
- package/dist/components/organisms/CanvasEditor/CanvasEditorStory.svelte +329 -0
- package/dist/components/organisms/CanvasEditor/CanvasEditorStory.svelte.d.ts +3 -0
- package/dist/components/organisms/DashboardBuilderPage/DashboardBuilderPage.svelte.d.ts +1 -1
- package/dist/components/organisms/DesktopShell/DesktopShell.svelte.d.ts +1 -1
- package/dist/components/organisms/EditorShell/EditorShell.svelte +162 -57
- package/dist/components/organisms/EditorShell/EditorShell.svelte.d.ts +21 -1
- package/dist/components/organisms/FileUploader/FileUploader.stories.d.ts +10 -0
- package/dist/components/organisms/FileUploader/FileUploader.stories.js +21 -0
- package/dist/components/organisms/FileUploader/FileUploader.svelte +127 -25
- package/dist/components/organisms/FileUploader/FileUploader.svelte.d.ts +20 -0
- package/dist/components/organisms/FileUploader/FileUploaderStory.svelte +7 -1
- package/dist/components/organisms/FileUploader/FileUploaderStory.svelte.d.ts +3 -0
- package/dist/components/organisms/ImportWizard/ImportWizard.stories.js +8 -0
- package/dist/components/organisms/ImportWizard/ImportWizard.svelte +209 -0
- package/dist/components/organisms/ImportWizard/ImportWizard.svelte.d.ts +22 -0
- package/dist/components/organisms/ImportWizard/ImportWizardStory.svelte +16 -0
- package/dist/components/organisms/ImportWizard/ImportWizardStory.svelte.d.ts +18 -0
- package/dist/components/organisms/VideoEditor/VideoEditor.stories.d.ts +12 -0
- package/dist/components/organisms/VideoEditor/VideoEditor.stories.js +9 -0
- package/dist/components/organisms/VideoEditor/VideoEditor.svelte +1687 -0
- package/dist/components/organisms/VideoEditor/VideoEditor.svelte.d.ts +14 -0
- package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte +11 -0
- package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte.d.ts +3 -0
- package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.stories.d.ts +12 -0
- package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.stories.js +9 -0
- package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.svelte +22 -0
- package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.svelte.d.ts +13 -0
- package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplateStory.svelte +8 -0
- package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplateStory.svelte.d.ts +3 -0
- package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.stories.d.ts +12 -0
- package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.stories.js +9 -0
- package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.svelte +32 -0
- package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.svelte.d.ts +17 -0
- package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplateStory.svelte +21 -0
- package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplateStory.svelte.d.ts +3 -0
- package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.stories.d.ts +12 -0
- package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.stories.js +9 -0
- package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.svelte +22 -0
- package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.svelte.d.ts +13 -0
- package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplateStory.svelte +8 -0
- package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplateStory.svelte.d.ts +3 -0
- package/dist/index.d.ts +91 -1
- package/dist/index.js +64 -0
- package/dist/types/xyflow-svelte.d.ts +62 -0
- package/dist/utils/audioProject.d.ts +19 -0
- package/dist/utils/audioProject.js +70 -0
- package/dist/utils/blogDocument.d.ts +175 -0
- package/dist/utils/blogDocument.js +220 -0
- package/dist/utils/blueprintRuntime.d.ts +34 -0
- package/dist/utils/blueprintRuntime.js +289 -0
- package/dist/utils/canvasDocument.d.ts +239 -0
- package/dist/utils/canvasDocument.js +443 -0
- package/dist/utils/canvasExport.d.ts +10 -0
- package/dist/utils/canvasExport.js +469 -0
- package/dist/utils/canvasHierarchy.d.ts +189 -0
- package/dist/utils/canvasHierarchy.js +674 -0
- package/dist/utils/canvasHistory.d.ts +19 -0
- package/dist/utils/canvasHistory.js +48 -0
- package/dist/utils/canvasWidget.d.ts +81 -0
- package/dist/utils/canvasWidget.js +597 -0
- package/dist/utils/mediaTime.d.ts +26 -0
- package/dist/utils/mediaTime.js +76 -0
- package/dist/utils/mediaTracks.d.ts +215 -0
- package/dist/utils/mediaTracks.js +798 -0
- package/dist/utils/nodeGraph.d.ts +354 -0
- package/dist/utils/nodeGraph.js +1453 -0
- package/dist/utils/queryBridge.d.ts +18 -0
- package/dist/utils/queryBridge.js +118 -0
- package/dist/utils/videoSequence.d.ts +13 -0
- package/dist/utils/videoSequence.js +94 -0
- package/package.json +5 -2
|
@@ -0,0 +1,1208 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Button from '../../atoms/Button/Button.svelte';
|
|
3
|
+
import Input from '../../atoms/Input/Input.svelte';
|
|
4
|
+
import Textarea from '../../atoms/Textarea/Textarea.svelte';
|
|
5
|
+
import Select from '../../molecules/Select/Select.svelte';
|
|
6
|
+
import JSONViewer from '../../molecules/JSONViewer/JSONViewer.svelte';
|
|
7
|
+
import {
|
|
8
|
+
NATIVE_BLOCK_TYPES,
|
|
9
|
+
createBlock,
|
|
10
|
+
createComponentBlock,
|
|
11
|
+
emptyBlogDocument,
|
|
12
|
+
getBlogComponent,
|
|
13
|
+
listBlogComponents,
|
|
14
|
+
type BlogAlign,
|
|
15
|
+
type BlogBlock,
|
|
16
|
+
type BlogBlockType,
|
|
17
|
+
type BlogCalloutData,
|
|
18
|
+
type BlogCodeData,
|
|
19
|
+
type BlogComponentData,
|
|
20
|
+
type BlogCtaData,
|
|
21
|
+
type BlogDividerData,
|
|
22
|
+
type BlogDocument,
|
|
23
|
+
type BlogEmbedData,
|
|
24
|
+
type BlogGalleryData,
|
|
25
|
+
type BlogHeadingData,
|
|
26
|
+
type BlogHtmlData,
|
|
27
|
+
type BlogImageData,
|
|
28
|
+
type BlogListData,
|
|
29
|
+
type BlogMarkdownData,
|
|
30
|
+
type BlogParagraphData,
|
|
31
|
+
type BlogQuoteData,
|
|
32
|
+
type BlogSpacerData,
|
|
33
|
+
type BlogTableData,
|
|
34
|
+
type BlogVideoData,
|
|
35
|
+
type BlogWidth
|
|
36
|
+
} from '../../../utils/blogDocument.js';
|
|
37
|
+
|
|
38
|
+
export type { BlogDocument, BlogBlock, BlogBlockType };
|
|
39
|
+
|
|
40
|
+
interface BlogEditorProps {
|
|
41
|
+
value?: BlogDocument;
|
|
42
|
+
showJson?: boolean;
|
|
43
|
+
showMeta?: boolean;
|
|
44
|
+
compact?: boolean;
|
|
45
|
+
class?: string;
|
|
46
|
+
onchange?: (doc: BlogDocument) => void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let {
|
|
50
|
+
value = $bindable(emptyBlogDocument()),
|
|
51
|
+
showJson = true,
|
|
52
|
+
showMeta = true,
|
|
53
|
+
compact = false,
|
|
54
|
+
class: className = '',
|
|
55
|
+
onchange
|
|
56
|
+
}: BlogEditorProps = $props();
|
|
57
|
+
|
|
58
|
+
let addMenuOpen = $state(false);
|
|
59
|
+
let componentMenuOpen = $state(false);
|
|
60
|
+
let metaOpen = $state(true);
|
|
61
|
+
|
|
62
|
+
const registered = $derived(listBlogComponents());
|
|
63
|
+
const blockGroups = $derived(
|
|
64
|
+
NATIVE_BLOCK_TYPES.reduce(
|
|
65
|
+
(acc, item) => {
|
|
66
|
+
(acc[item.group] ??= []).push(item);
|
|
67
|
+
return acc;
|
|
68
|
+
},
|
|
69
|
+
{} as Record<string, typeof NATIVE_BLOCK_TYPES>
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const ALIGN_OPTS = [
|
|
74
|
+
{ value: 'left', label: 'Left' },
|
|
75
|
+
{ value: 'center', label: 'Center' },
|
|
76
|
+
{ value: 'right', label: 'Right' }
|
|
77
|
+
];
|
|
78
|
+
const WIDTH_OPTS = [
|
|
79
|
+
{ value: 'narrow', label: 'Narrow' },
|
|
80
|
+
{ value: 'content', label: 'Content' },
|
|
81
|
+
{ value: 'wide', label: 'Wide' },
|
|
82
|
+
{ value: 'full', label: 'Full' }
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
function emit(next: BlogDocument) {
|
|
86
|
+
value = next;
|
|
87
|
+
onchange?.(next);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function patchMeta(patch: Partial<BlogDocument>) {
|
|
91
|
+
emit({ ...value, ...patch });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function addNative(type: Exclude<BlogBlockType, 'component'>) {
|
|
95
|
+
emit({ ...value, blocks: [...value.blocks, createBlock(type)] });
|
|
96
|
+
addMenuOpen = false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function addComponent(id: string) {
|
|
100
|
+
emit({ ...value, blocks: [...value.blocks, createComponentBlock(id)] });
|
|
101
|
+
componentMenuOpen = false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function updateBlock(id: string, data: BlogBlock['data']) {
|
|
105
|
+
emit({
|
|
106
|
+
...value,
|
|
107
|
+
blocks: value.blocks.map((b) => (b.id === id ? { ...b, data } : b))
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function removeBlock(id: string) {
|
|
112
|
+
emit({ ...value, blocks: value.blocks.filter((b) => b.id !== id) });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function duplicateBlock(id: string) {
|
|
116
|
+
const idx = value.blocks.findIndex((b) => b.id === id);
|
|
117
|
+
if (idx < 0) return;
|
|
118
|
+
const copy = createBlock(value.blocks[idx].type, {
|
|
119
|
+
...(value.blocks[idx].data as object)
|
|
120
|
+
} as never);
|
|
121
|
+
const blocks = [...value.blocks];
|
|
122
|
+
blocks.splice(idx + 1, 0, copy);
|
|
123
|
+
emit({ ...value, blocks });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function moveBlock(id: string, dir: -1 | 1) {
|
|
127
|
+
const idx = value.blocks.findIndex((b) => b.id === id);
|
|
128
|
+
if (idx < 0) return;
|
|
129
|
+
const nextIdx = idx + dir;
|
|
130
|
+
if (nextIdx < 0 || nextIdx >= value.blocks.length) return;
|
|
131
|
+
const blocks = [...value.blocks];
|
|
132
|
+
const [item] = blocks.splice(idx, 1);
|
|
133
|
+
blocks.splice(nextIdx, 0, item);
|
|
134
|
+
emit({ ...value, blocks });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function blockLabel(type: string): string {
|
|
138
|
+
return NATIVE_BLOCK_TYPES.find((t) => t.type === type)?.label ?? type;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function updateComponentProp(blockId: string, data: BlogComponentData, key: string, raw: unknown) {
|
|
142
|
+
updateBlock(blockId, {
|
|
143
|
+
...data,
|
|
144
|
+
props: { ...(data.props ?? {}), [key]: raw }
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
</script>
|
|
148
|
+
|
|
149
|
+
<div
|
|
150
|
+
class={[
|
|
151
|
+
'flex flex-col gap-4 border border-border bg-surface-elevated',
|
|
152
|
+
compact ? 'rounded-lg p-3' : 'rounded-xl p-4',
|
|
153
|
+
className
|
|
154
|
+
]}
|
|
155
|
+
data-blog-editor
|
|
156
|
+
>
|
|
157
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
158
|
+
<Input
|
|
159
|
+
value={value.title ?? ''}
|
|
160
|
+
placeholder="Post title"
|
|
161
|
+
class="min-w-[12rem] flex-1"
|
|
162
|
+
oninput={(e) => patchMeta({ title: (e.currentTarget as HTMLInputElement).value })}
|
|
163
|
+
/>
|
|
164
|
+
{#if showMeta}
|
|
165
|
+
<Button size="sm" variant="ghost" onclick={() => (metaOpen = !metaOpen)}>
|
|
166
|
+
{metaOpen ? 'Hide meta' : 'Meta'}
|
|
167
|
+
</Button>
|
|
168
|
+
{/if}
|
|
169
|
+
<div class="relative">
|
|
170
|
+
<Button size="sm" variant="secondary" onclick={() => (addMenuOpen = !addMenuOpen)}>
|
|
171
|
+
Add block
|
|
172
|
+
</Button>
|
|
173
|
+
{#if addMenuOpen}
|
|
174
|
+
<div
|
|
175
|
+
class="absolute right-0 z-20 mt-1 max-h-80 w-56 overflow-auto rounded-xl border border-border bg-surface-elevated py-1 shadow-lg"
|
|
176
|
+
>
|
|
177
|
+
{#each Object.entries(blockGroups) as [group, items] (group)}
|
|
178
|
+
<p class="px-3 pb-0.5 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted">
|
|
179
|
+
{group}
|
|
180
|
+
</p>
|
|
181
|
+
{#each items as item (item.type)}
|
|
182
|
+
<button
|
|
183
|
+
type="button"
|
|
184
|
+
class="block w-full px-3 py-1.5 text-left text-sm text-primary hover:bg-surface-overlay"
|
|
185
|
+
onclick={() => addNative(item.type)}
|
|
186
|
+
>
|
|
187
|
+
{item.label}
|
|
188
|
+
</button>
|
|
189
|
+
{/each}
|
|
190
|
+
{/each}
|
|
191
|
+
</div>
|
|
192
|
+
{/if}
|
|
193
|
+
</div>
|
|
194
|
+
{#if registered.length}
|
|
195
|
+
<div class="relative">
|
|
196
|
+
<Button
|
|
197
|
+
size="sm"
|
|
198
|
+
variant="secondary"
|
|
199
|
+
onclick={() => (componentMenuOpen = !componentMenuOpen)}
|
|
200
|
+
>
|
|
201
|
+
Add component
|
|
202
|
+
</Button>
|
|
203
|
+
{#if componentMenuOpen}
|
|
204
|
+
<div
|
|
205
|
+
class="absolute right-0 z-20 mt-1 w-60 overflow-hidden rounded-xl border border-border bg-surface-elevated py-1 shadow-lg"
|
|
206
|
+
>
|
|
207
|
+
{#each registered as item (item.id)}
|
|
208
|
+
<button
|
|
209
|
+
type="button"
|
|
210
|
+
class="block w-full px-3 py-1.5 text-left hover:bg-surface-overlay"
|
|
211
|
+
onclick={() => addComponent(item.id)}
|
|
212
|
+
>
|
|
213
|
+
<span class="block text-sm text-primary">{item.registration.label}</span>
|
|
214
|
+
{#if item.registration.description}
|
|
215
|
+
<span class="block text-[11px] text-muted">{item.registration.description}</span>
|
|
216
|
+
{/if}
|
|
217
|
+
</button>
|
|
218
|
+
{/each}
|
|
219
|
+
</div>
|
|
220
|
+
{/if}
|
|
221
|
+
</div>
|
|
222
|
+
{/if}
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
{#if showMeta && metaOpen}
|
|
226
|
+
<div class="grid gap-2 rounded-xl border border-border bg-surface-overlay/30 p-3 sm:grid-cols-2">
|
|
227
|
+
<Input
|
|
228
|
+
value={value.description ?? ''}
|
|
229
|
+
placeholder="Description / deck"
|
|
230
|
+
class="sm:col-span-2"
|
|
231
|
+
oninput={(e) => patchMeta({ description: (e.currentTarget as HTMLInputElement).value })}
|
|
232
|
+
/>
|
|
233
|
+
<Input
|
|
234
|
+
value={value.author ?? ''}
|
|
235
|
+
placeholder="Author"
|
|
236
|
+
oninput={(e) => patchMeta({ author: (e.currentTarget as HTMLInputElement).value })}
|
|
237
|
+
/>
|
|
238
|
+
<Input
|
|
239
|
+
value={value.publishedAt ?? ''}
|
|
240
|
+
placeholder="Published at (ISO or text)"
|
|
241
|
+
oninput={(e) => patchMeta({ publishedAt: (e.currentTarget as HTMLInputElement).value })}
|
|
242
|
+
/>
|
|
243
|
+
<Input
|
|
244
|
+
value={value.coverImage ?? ''}
|
|
245
|
+
placeholder="Cover image URL"
|
|
246
|
+
class="sm:col-span-2"
|
|
247
|
+
oninput={(e) => patchMeta({ coverImage: (e.currentTarget as HTMLInputElement).value })}
|
|
248
|
+
/>
|
|
249
|
+
<Input
|
|
250
|
+
value={(value.tags ?? []).join(', ')}
|
|
251
|
+
placeholder="Tags (comma separated)"
|
|
252
|
+
class="sm:col-span-2"
|
|
253
|
+
oninput={(e) =>
|
|
254
|
+
patchMeta({
|
|
255
|
+
tags: (e.currentTarget as HTMLInputElement).value
|
|
256
|
+
.split(',')
|
|
257
|
+
.map((t) => t.trim())
|
|
258
|
+
.filter(Boolean)
|
|
259
|
+
})}
|
|
260
|
+
/>
|
|
261
|
+
</div>
|
|
262
|
+
{/if}
|
|
263
|
+
|
|
264
|
+
{#if value.blocks.length === 0}
|
|
265
|
+
<p class="rounded-lg border border-dashed border-border px-3 py-8 text-center text-sm text-muted">
|
|
266
|
+
No blocks yet. Add a block or component to start.
|
|
267
|
+
</p>
|
|
268
|
+
{:else}
|
|
269
|
+
<ul class="flex flex-col gap-3">
|
|
270
|
+
{#each value.blocks as block, i (block.id)}
|
|
271
|
+
<li class="rounded-xl border border-border bg-surface-overlay/40 p-3">
|
|
272
|
+
<div class="mb-2 flex items-center justify-between gap-2">
|
|
273
|
+
<span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
274
|
+
{blockLabel(block.type)}
|
|
275
|
+
</span>
|
|
276
|
+
<div class="flex items-center gap-1">
|
|
277
|
+
<Button
|
|
278
|
+
size="sm"
|
|
279
|
+
variant="ghost"
|
|
280
|
+
disabled={i === 0}
|
|
281
|
+
onclick={() => moveBlock(block.id, -1)}
|
|
282
|
+
>
|
|
283
|
+
↑
|
|
284
|
+
</Button>
|
|
285
|
+
<Button
|
|
286
|
+
size="sm"
|
|
287
|
+
variant="ghost"
|
|
288
|
+
disabled={i === value.blocks.length - 1}
|
|
289
|
+
onclick={() => moveBlock(block.id, 1)}
|
|
290
|
+
>
|
|
291
|
+
↓
|
|
292
|
+
</Button>
|
|
293
|
+
<Button size="sm" variant="ghost" onclick={() => duplicateBlock(block.id)}>
|
|
294
|
+
Duplicate
|
|
295
|
+
</Button>
|
|
296
|
+
<Button size="sm" variant="ghost" onclick={() => removeBlock(block.id)}>
|
|
297
|
+
Remove
|
|
298
|
+
</Button>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
{#if block.type === 'heading'}
|
|
303
|
+
{@const data = block.data as BlogHeadingData}
|
|
304
|
+
<div class="flex flex-col gap-2">
|
|
305
|
+
<div class="flex flex-wrap gap-2">
|
|
306
|
+
<Select
|
|
307
|
+
value={String(data.level)}
|
|
308
|
+
options={[
|
|
309
|
+
{ value: '1', label: 'H1' },
|
|
310
|
+
{ value: '2', label: 'H2' },
|
|
311
|
+
{ value: '3', label: 'H3' },
|
|
312
|
+
{ value: '4', label: 'H4' }
|
|
313
|
+
]}
|
|
314
|
+
onchange={(v) =>
|
|
315
|
+
updateBlock(block.id, {
|
|
316
|
+
...data,
|
|
317
|
+
level: Number(v) as BlogHeadingData['level']
|
|
318
|
+
})}
|
|
319
|
+
class="w-24"
|
|
320
|
+
/>
|
|
321
|
+
<Select
|
|
322
|
+
value={data.align ?? 'left'}
|
|
323
|
+
options={ALIGN_OPTS}
|
|
324
|
+
onchange={(v) => updateBlock(block.id, { ...data, align: v as BlogAlign })}
|
|
325
|
+
class="w-28"
|
|
326
|
+
/>
|
|
327
|
+
<Input
|
|
328
|
+
value={data.anchor ?? ''}
|
|
329
|
+
placeholder="Anchor id"
|
|
330
|
+
class="w-36"
|
|
331
|
+
oninput={(e) =>
|
|
332
|
+
updateBlock(block.id, {
|
|
333
|
+
...data,
|
|
334
|
+
anchor: (e.currentTarget as HTMLInputElement).value
|
|
335
|
+
})}
|
|
336
|
+
/>
|
|
337
|
+
</div>
|
|
338
|
+
<Input
|
|
339
|
+
value={data.text}
|
|
340
|
+
oninput={(e) =>
|
|
341
|
+
updateBlock(block.id, {
|
|
342
|
+
...data,
|
|
343
|
+
text: (e.currentTarget as HTMLInputElement).value
|
|
344
|
+
})}
|
|
345
|
+
/>
|
|
346
|
+
</div>
|
|
347
|
+
{:else if block.type === 'paragraph'}
|
|
348
|
+
{@const data = block.data as BlogParagraphData}
|
|
349
|
+
<div class="flex flex-col gap-2">
|
|
350
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
351
|
+
<Select
|
|
352
|
+
value={data.align ?? 'left'}
|
|
353
|
+
options={ALIGN_OPTS}
|
|
354
|
+
onchange={(v) => updateBlock(block.id, { ...data, align: v as BlogAlign })}
|
|
355
|
+
class="w-28"
|
|
356
|
+
/>
|
|
357
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
358
|
+
<input
|
|
359
|
+
type="checkbox"
|
|
360
|
+
checked={!!data.lead}
|
|
361
|
+
onchange={(e) =>
|
|
362
|
+
updateBlock(block.id, {
|
|
363
|
+
...data,
|
|
364
|
+
lead: (e.currentTarget as HTMLInputElement).checked
|
|
365
|
+
})}
|
|
366
|
+
/>
|
|
367
|
+
Lead
|
|
368
|
+
</label>
|
|
369
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
370
|
+
<input
|
|
371
|
+
type="checkbox"
|
|
372
|
+
checked={!!data.muted}
|
|
373
|
+
onchange={(e) =>
|
|
374
|
+
updateBlock(block.id, {
|
|
375
|
+
...data,
|
|
376
|
+
muted: (e.currentTarget as HTMLInputElement).checked
|
|
377
|
+
})}
|
|
378
|
+
/>
|
|
379
|
+
Muted
|
|
380
|
+
</label>
|
|
381
|
+
</div>
|
|
382
|
+
<Textarea
|
|
383
|
+
value={data.text}
|
|
384
|
+
rows={3}
|
|
385
|
+
oninput={(e) =>
|
|
386
|
+
updateBlock(block.id, {
|
|
387
|
+
...data,
|
|
388
|
+
text: (e.currentTarget as HTMLTextAreaElement).value
|
|
389
|
+
})}
|
|
390
|
+
/>
|
|
391
|
+
</div>
|
|
392
|
+
{:else if block.type === 'image'}
|
|
393
|
+
{@const data = block.data as BlogImageData}
|
|
394
|
+
<div class="grid gap-2 sm:grid-cols-2">
|
|
395
|
+
<Input
|
|
396
|
+
value={data.src}
|
|
397
|
+
placeholder="Image URL"
|
|
398
|
+
class="sm:col-span-2"
|
|
399
|
+
oninput={(e) =>
|
|
400
|
+
updateBlock(block.id, {
|
|
401
|
+
...data,
|
|
402
|
+
src: (e.currentTarget as HTMLInputElement).value
|
|
403
|
+
})}
|
|
404
|
+
/>
|
|
405
|
+
<Input
|
|
406
|
+
value={data.alt ?? ''}
|
|
407
|
+
placeholder="Alt text"
|
|
408
|
+
oninput={(e) =>
|
|
409
|
+
updateBlock(block.id, {
|
|
410
|
+
...data,
|
|
411
|
+
alt: (e.currentTarget as HTMLInputElement).value
|
|
412
|
+
})}
|
|
413
|
+
/>
|
|
414
|
+
<Input
|
|
415
|
+
value={data.caption ?? ''}
|
|
416
|
+
placeholder="Caption"
|
|
417
|
+
oninput={(e) =>
|
|
418
|
+
updateBlock(block.id, {
|
|
419
|
+
...data,
|
|
420
|
+
caption: (e.currentTarget as HTMLInputElement).value
|
|
421
|
+
})}
|
|
422
|
+
/>
|
|
423
|
+
<Input
|
|
424
|
+
value={data.href ?? ''}
|
|
425
|
+
placeholder="Link URL (optional)"
|
|
426
|
+
class="sm:col-span-2"
|
|
427
|
+
oninput={(e) =>
|
|
428
|
+
updateBlock(block.id, {
|
|
429
|
+
...data,
|
|
430
|
+
href: (e.currentTarget as HTMLInputElement).value
|
|
431
|
+
})}
|
|
432
|
+
/>
|
|
433
|
+
<Select
|
|
434
|
+
value={data.align ?? 'center'}
|
|
435
|
+
options={ALIGN_OPTS}
|
|
436
|
+
onchange={(v) => updateBlock(block.id, { ...data, align: v as BlogAlign })}
|
|
437
|
+
/>
|
|
438
|
+
<Select
|
|
439
|
+
value={data.width ?? 'content'}
|
|
440
|
+
options={WIDTH_OPTS}
|
|
441
|
+
onchange={(v) => updateBlock(block.id, { ...data, width: v as BlogWidth })}
|
|
442
|
+
/>
|
|
443
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
444
|
+
<input
|
|
445
|
+
type="checkbox"
|
|
446
|
+
checked={data.rounded !== false}
|
|
447
|
+
onchange={(e) =>
|
|
448
|
+
updateBlock(block.id, {
|
|
449
|
+
...data,
|
|
450
|
+
rounded: (e.currentTarget as HTMLInputElement).checked
|
|
451
|
+
})}
|
|
452
|
+
/>
|
|
453
|
+
Rounded
|
|
454
|
+
</label>
|
|
455
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
456
|
+
<input
|
|
457
|
+
type="checkbox"
|
|
458
|
+
checked={!!data.shadow}
|
|
459
|
+
onchange={(e) =>
|
|
460
|
+
updateBlock(block.id, {
|
|
461
|
+
...data,
|
|
462
|
+
shadow: (e.currentTarget as HTMLInputElement).checked
|
|
463
|
+
})}
|
|
464
|
+
/>
|
|
465
|
+
Shadow
|
|
466
|
+
</label>
|
|
467
|
+
</div>
|
|
468
|
+
{:else if block.type === 'code'}
|
|
469
|
+
{@const data = block.data as BlogCodeData}
|
|
470
|
+
<div class="flex flex-col gap-2">
|
|
471
|
+
<div class="flex flex-wrap gap-2">
|
|
472
|
+
<Input
|
|
473
|
+
value={data.language ?? ''}
|
|
474
|
+
placeholder="Language"
|
|
475
|
+
class="w-36"
|
|
476
|
+
oninput={(e) =>
|
|
477
|
+
updateBlock(block.id, {
|
|
478
|
+
...data,
|
|
479
|
+
language: (e.currentTarget as HTMLInputElement).value
|
|
480
|
+
})}
|
|
481
|
+
/>
|
|
482
|
+
<Input
|
|
483
|
+
value={data.filename ?? ''}
|
|
484
|
+
placeholder="Filename"
|
|
485
|
+
class="flex-1"
|
|
486
|
+
oninput={(e) =>
|
|
487
|
+
updateBlock(block.id, {
|
|
488
|
+
...data,
|
|
489
|
+
filename: (e.currentTarget as HTMLInputElement).value
|
|
490
|
+
})}
|
|
491
|
+
/>
|
|
492
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
493
|
+
<input
|
|
494
|
+
type="checkbox"
|
|
495
|
+
checked={!!data.showLineNumbers}
|
|
496
|
+
onchange={(e) =>
|
|
497
|
+
updateBlock(block.id, {
|
|
498
|
+
...data,
|
|
499
|
+
showLineNumbers: (e.currentTarget as HTMLInputElement).checked
|
|
500
|
+
})}
|
|
501
|
+
/>
|
|
502
|
+
Line numbers
|
|
503
|
+
</label>
|
|
504
|
+
</div>
|
|
505
|
+
<Input
|
|
506
|
+
value={data.highlightLines ?? ''}
|
|
507
|
+
placeholder="Highlight lines (e.g. 1,3-5)"
|
|
508
|
+
oninput={(e) =>
|
|
509
|
+
updateBlock(block.id, {
|
|
510
|
+
...data,
|
|
511
|
+
highlightLines: (e.currentTarget as HTMLInputElement).value
|
|
512
|
+
})}
|
|
513
|
+
/>
|
|
514
|
+
<Textarea
|
|
515
|
+
value={data.code}
|
|
516
|
+
rows={6}
|
|
517
|
+
class="font-mono text-xs"
|
|
518
|
+
oninput={(e) =>
|
|
519
|
+
updateBlock(block.id, {
|
|
520
|
+
...data,
|
|
521
|
+
code: (e.currentTarget as HTMLTextAreaElement).value
|
|
522
|
+
})}
|
|
523
|
+
/>
|
|
524
|
+
</div>
|
|
525
|
+
{:else if block.type === 'callout'}
|
|
526
|
+
{@const data = block.data as BlogCalloutData}
|
|
527
|
+
<div class="flex flex-col gap-2">
|
|
528
|
+
<div class="flex flex-wrap gap-2">
|
|
529
|
+
<Select
|
|
530
|
+
value={data.tone ?? 'info'}
|
|
531
|
+
options={[
|
|
532
|
+
{ value: 'info', label: 'Info' },
|
|
533
|
+
{ value: 'success', label: 'Success' },
|
|
534
|
+
{ value: 'warning', label: 'Warning' },
|
|
535
|
+
{ value: 'danger', label: 'Danger' },
|
|
536
|
+
{ value: 'neutral', label: 'Neutral' }
|
|
537
|
+
]}
|
|
538
|
+
onchange={(v) =>
|
|
539
|
+
updateBlock(block.id, {
|
|
540
|
+
...data,
|
|
541
|
+
tone: v as BlogCalloutData['tone']
|
|
542
|
+
})}
|
|
543
|
+
class="w-36"
|
|
544
|
+
/>
|
|
545
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
546
|
+
<input
|
|
547
|
+
type="checkbox"
|
|
548
|
+
checked={!!data.collapsible}
|
|
549
|
+
onchange={(e) =>
|
|
550
|
+
updateBlock(block.id, {
|
|
551
|
+
...data,
|
|
552
|
+
collapsible: (e.currentTarget as HTMLInputElement).checked
|
|
553
|
+
})}
|
|
554
|
+
/>
|
|
555
|
+
Collapsible
|
|
556
|
+
</label>
|
|
557
|
+
</div>
|
|
558
|
+
<Input
|
|
559
|
+
value={data.title ?? ''}
|
|
560
|
+
placeholder="Title"
|
|
561
|
+
oninput={(e) =>
|
|
562
|
+
updateBlock(block.id, {
|
|
563
|
+
...data,
|
|
564
|
+
title: (e.currentTarget as HTMLInputElement).value
|
|
565
|
+
})}
|
|
566
|
+
/>
|
|
567
|
+
<Textarea
|
|
568
|
+
value={data.text}
|
|
569
|
+
rows={3}
|
|
570
|
+
oninput={(e) =>
|
|
571
|
+
updateBlock(block.id, {
|
|
572
|
+
...data,
|
|
573
|
+
text: (e.currentTarget as HTMLTextAreaElement).value
|
|
574
|
+
})}
|
|
575
|
+
/>
|
|
576
|
+
</div>
|
|
577
|
+
{:else if block.type === 'quote'}
|
|
578
|
+
{@const data = block.data as BlogQuoteData}
|
|
579
|
+
<div class="flex flex-col gap-2">
|
|
580
|
+
<Select
|
|
581
|
+
value={data.align ?? 'left'}
|
|
582
|
+
options={ALIGN_OPTS}
|
|
583
|
+
onchange={(v) => updateBlock(block.id, { ...data, align: v as BlogAlign })}
|
|
584
|
+
class="w-28"
|
|
585
|
+
/>
|
|
586
|
+
<Textarea
|
|
587
|
+
value={data.text}
|
|
588
|
+
rows={3}
|
|
589
|
+
oninput={(e) =>
|
|
590
|
+
updateBlock(block.id, {
|
|
591
|
+
...data,
|
|
592
|
+
text: (e.currentTarget as HTMLTextAreaElement).value
|
|
593
|
+
})}
|
|
594
|
+
/>
|
|
595
|
+
<div class="flex gap-2">
|
|
596
|
+
<Input
|
|
597
|
+
value={data.cite ?? ''}
|
|
598
|
+
placeholder="Author"
|
|
599
|
+
class="flex-1"
|
|
600
|
+
oninput={(e) =>
|
|
601
|
+
updateBlock(block.id, {
|
|
602
|
+
...data,
|
|
603
|
+
cite: (e.currentTarget as HTMLInputElement).value
|
|
604
|
+
})}
|
|
605
|
+
/>
|
|
606
|
+
<Input
|
|
607
|
+
value={data.role ?? ''}
|
|
608
|
+
placeholder="Role"
|
|
609
|
+
class="flex-1"
|
|
610
|
+
oninput={(e) =>
|
|
611
|
+
updateBlock(block.id, {
|
|
612
|
+
...data,
|
|
613
|
+
role: (e.currentTarget as HTMLInputElement).value
|
|
614
|
+
})}
|
|
615
|
+
/>
|
|
616
|
+
</div>
|
|
617
|
+
</div>
|
|
618
|
+
{:else if block.type === 'list'}
|
|
619
|
+
{@const data = block.data as BlogListData}
|
|
620
|
+
<div class="flex flex-col gap-2">
|
|
621
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
622
|
+
<label class="flex items-center gap-2 text-xs text-muted">
|
|
623
|
+
<input
|
|
624
|
+
type="checkbox"
|
|
625
|
+
checked={!!data.ordered}
|
|
626
|
+
onchange={(e) =>
|
|
627
|
+
updateBlock(block.id, {
|
|
628
|
+
...data,
|
|
629
|
+
ordered: (e.currentTarget as HTMLInputElement).checked
|
|
630
|
+
})}
|
|
631
|
+
/>
|
|
632
|
+
Ordered
|
|
633
|
+
</label>
|
|
634
|
+
<label class="flex items-center gap-2 text-xs text-muted">
|
|
635
|
+
<input
|
|
636
|
+
type="checkbox"
|
|
637
|
+
checked={!!data.tight}
|
|
638
|
+
onchange={(e) =>
|
|
639
|
+
updateBlock(block.id, {
|
|
640
|
+
...data,
|
|
641
|
+
tight: (e.currentTarget as HTMLInputElement).checked
|
|
642
|
+
})}
|
|
643
|
+
/>
|
|
644
|
+
Tight
|
|
645
|
+
</label>
|
|
646
|
+
{#if data.ordered}
|
|
647
|
+
<Input
|
|
648
|
+
type="number"
|
|
649
|
+
value={String(data.start ?? 1)}
|
|
650
|
+
placeholder="Start"
|
|
651
|
+
class="w-24"
|
|
652
|
+
oninput={(e) =>
|
|
653
|
+
updateBlock(block.id, {
|
|
654
|
+
...data,
|
|
655
|
+
start: Number((e.currentTarget as HTMLInputElement).value) || 1
|
|
656
|
+
})}
|
|
657
|
+
/>
|
|
658
|
+
{/if}
|
|
659
|
+
</div>
|
|
660
|
+
<Textarea
|
|
661
|
+
value={data.items.join('\n')}
|
|
662
|
+
rows={4}
|
|
663
|
+
placeholder="One item per line"
|
|
664
|
+
oninput={(e) =>
|
|
665
|
+
updateBlock(block.id, {
|
|
666
|
+
...data,
|
|
667
|
+
items: (e.currentTarget as HTMLTextAreaElement).value.split('\n')
|
|
668
|
+
})}
|
|
669
|
+
/>
|
|
670
|
+
</div>
|
|
671
|
+
{:else if block.type === 'markdown'}
|
|
672
|
+
{@const data = block.data as BlogMarkdownData}
|
|
673
|
+
<Textarea
|
|
674
|
+
value={data.source}
|
|
675
|
+
rows={6}
|
|
676
|
+
class="font-mono text-xs"
|
|
677
|
+
oninput={(e) =>
|
|
678
|
+
updateBlock(block.id, {
|
|
679
|
+
...data,
|
|
680
|
+
source: (e.currentTarget as HTMLTextAreaElement).value
|
|
681
|
+
})}
|
|
682
|
+
/>
|
|
683
|
+
{:else if block.type === 'divider'}
|
|
684
|
+
{@const data = block.data as BlogDividerData}
|
|
685
|
+
<div class="flex flex-wrap gap-2">
|
|
686
|
+
<Select
|
|
687
|
+
value={data.style ?? 'solid'}
|
|
688
|
+
options={[
|
|
689
|
+
{ value: 'solid', label: 'Solid' },
|
|
690
|
+
{ value: 'dashed', label: 'Dashed' },
|
|
691
|
+
{ value: 'dotted', label: 'Dotted' }
|
|
692
|
+
]}
|
|
693
|
+
onchange={(v) =>
|
|
694
|
+
updateBlock(block.id, {
|
|
695
|
+
...data,
|
|
696
|
+
style: v as BlogDividerData['style']
|
|
697
|
+
})}
|
|
698
|
+
class="w-32"
|
|
699
|
+
/>
|
|
700
|
+
<Select
|
|
701
|
+
value={data.spacing ?? 'md'}
|
|
702
|
+
options={[
|
|
703
|
+
{ value: 'sm', label: 'Spacing S' },
|
|
704
|
+
{ value: 'md', label: 'Spacing M' },
|
|
705
|
+
{ value: 'lg', label: 'Spacing L' }
|
|
706
|
+
]}
|
|
707
|
+
onchange={(v) =>
|
|
708
|
+
updateBlock(block.id, {
|
|
709
|
+
...data,
|
|
710
|
+
spacing: v as BlogDividerData['spacing']
|
|
711
|
+
})}
|
|
712
|
+
class="w-32"
|
|
713
|
+
/>
|
|
714
|
+
<Input
|
|
715
|
+
value={data.label ?? ''}
|
|
716
|
+
placeholder="Optional label"
|
|
717
|
+
class="flex-1"
|
|
718
|
+
oninput={(e) =>
|
|
719
|
+
updateBlock(block.id, {
|
|
720
|
+
...data,
|
|
721
|
+
label: (e.currentTarget as HTMLInputElement).value
|
|
722
|
+
})}
|
|
723
|
+
/>
|
|
724
|
+
</div>
|
|
725
|
+
{:else if block.type === 'video'}
|
|
726
|
+
{@const data = block.data as BlogVideoData}
|
|
727
|
+
<div class="grid gap-2 sm:grid-cols-2">
|
|
728
|
+
<Input
|
|
729
|
+
value={data.src}
|
|
730
|
+
placeholder="Video URL"
|
|
731
|
+
class="sm:col-span-2"
|
|
732
|
+
oninput={(e) =>
|
|
733
|
+
updateBlock(block.id, {
|
|
734
|
+
...data,
|
|
735
|
+
src: (e.currentTarget as HTMLInputElement).value
|
|
736
|
+
})}
|
|
737
|
+
/>
|
|
738
|
+
<Input
|
|
739
|
+
value={data.poster ?? ''}
|
|
740
|
+
placeholder="Poster image"
|
|
741
|
+
oninput={(e) =>
|
|
742
|
+
updateBlock(block.id, {
|
|
743
|
+
...data,
|
|
744
|
+
poster: (e.currentTarget as HTMLInputElement).value
|
|
745
|
+
})}
|
|
746
|
+
/>
|
|
747
|
+
<Input
|
|
748
|
+
value={data.caption ?? ''}
|
|
749
|
+
placeholder="Caption"
|
|
750
|
+
oninput={(e) =>
|
|
751
|
+
updateBlock(block.id, {
|
|
752
|
+
...data,
|
|
753
|
+
caption: (e.currentTarget as HTMLInputElement).value
|
|
754
|
+
})}
|
|
755
|
+
/>
|
|
756
|
+
<Select
|
|
757
|
+
value={data.align ?? 'center'}
|
|
758
|
+
options={ALIGN_OPTS}
|
|
759
|
+
onchange={(v) => updateBlock(block.id, { ...data, align: v as BlogAlign })}
|
|
760
|
+
/>
|
|
761
|
+
<Select
|
|
762
|
+
value={data.width ?? 'content'}
|
|
763
|
+
options={WIDTH_OPTS}
|
|
764
|
+
onchange={(v) => updateBlock(block.id, { ...data, width: v as BlogWidth })}
|
|
765
|
+
/>
|
|
766
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
767
|
+
<input
|
|
768
|
+
type="checkbox"
|
|
769
|
+
checked={data.controls !== false}
|
|
770
|
+
onchange={(e) =>
|
|
771
|
+
updateBlock(block.id, {
|
|
772
|
+
...data,
|
|
773
|
+
controls: (e.currentTarget as HTMLInputElement).checked
|
|
774
|
+
})}
|
|
775
|
+
/>
|
|
776
|
+
Controls
|
|
777
|
+
</label>
|
|
778
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
779
|
+
<input
|
|
780
|
+
type="checkbox"
|
|
781
|
+
checked={!!data.autoplay}
|
|
782
|
+
onchange={(e) =>
|
|
783
|
+
updateBlock(block.id, {
|
|
784
|
+
...data,
|
|
785
|
+
autoplay: (e.currentTarget as HTMLInputElement).checked
|
|
786
|
+
})}
|
|
787
|
+
/>
|
|
788
|
+
Autoplay
|
|
789
|
+
</label>
|
|
790
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
791
|
+
<input
|
|
792
|
+
type="checkbox"
|
|
793
|
+
checked={!!data.loop}
|
|
794
|
+
onchange={(e) =>
|
|
795
|
+
updateBlock(block.id, {
|
|
796
|
+
...data,
|
|
797
|
+
loop: (e.currentTarget as HTMLInputElement).checked
|
|
798
|
+
})}
|
|
799
|
+
/>
|
|
800
|
+
Loop
|
|
801
|
+
</label>
|
|
802
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
803
|
+
<input
|
|
804
|
+
type="checkbox"
|
|
805
|
+
checked={!!data.muted}
|
|
806
|
+
onchange={(e) =>
|
|
807
|
+
updateBlock(block.id, {
|
|
808
|
+
...data,
|
|
809
|
+
muted: (e.currentTarget as HTMLInputElement).checked
|
|
810
|
+
})}
|
|
811
|
+
/>
|
|
812
|
+
Muted
|
|
813
|
+
</label>
|
|
814
|
+
</div>
|
|
815
|
+
{:else if block.type === 'embed'}
|
|
816
|
+
{@const data = block.data as BlogEmbedData}
|
|
817
|
+
<div class="grid gap-2 sm:grid-cols-2">
|
|
818
|
+
<Input
|
|
819
|
+
value={data.url}
|
|
820
|
+
placeholder="YouTube / Vimeo / iframe URL"
|
|
821
|
+
class="sm:col-span-2"
|
|
822
|
+
oninput={(e) =>
|
|
823
|
+
updateBlock(block.id, {
|
|
824
|
+
...data,
|
|
825
|
+
url: (e.currentTarget as HTMLInputElement).value
|
|
826
|
+
})}
|
|
827
|
+
/>
|
|
828
|
+
<Input
|
|
829
|
+
value={data.title ?? ''}
|
|
830
|
+
placeholder="Title"
|
|
831
|
+
oninput={(e) =>
|
|
832
|
+
updateBlock(block.id, {
|
|
833
|
+
...data,
|
|
834
|
+
title: (e.currentTarget as HTMLInputElement).value
|
|
835
|
+
})}
|
|
836
|
+
/>
|
|
837
|
+
<Select
|
|
838
|
+
value={data.aspectRatio ?? '16:9'}
|
|
839
|
+
options={[
|
|
840
|
+
{ value: '16:9', label: '16:9' },
|
|
841
|
+
{ value: '4:3', label: '4:3' },
|
|
842
|
+
{ value: '1:1', label: '1:1' },
|
|
843
|
+
{ value: '9:16', label: '9:16' }
|
|
844
|
+
]}
|
|
845
|
+
onchange={(v) =>
|
|
846
|
+
updateBlock(block.id, {
|
|
847
|
+
...data,
|
|
848
|
+
aspectRatio: v as BlogEmbedData['aspectRatio']
|
|
849
|
+
})}
|
|
850
|
+
/>
|
|
851
|
+
<Input
|
|
852
|
+
value={data.caption ?? ''}
|
|
853
|
+
placeholder="Caption"
|
|
854
|
+
class="sm:col-span-2"
|
|
855
|
+
oninput={(e) =>
|
|
856
|
+
updateBlock(block.id, {
|
|
857
|
+
...data,
|
|
858
|
+
caption: (e.currentTarget as HTMLInputElement).value
|
|
859
|
+
})}
|
|
860
|
+
/>
|
|
861
|
+
</div>
|
|
862
|
+
{:else if block.type === 'gallery'}
|
|
863
|
+
{@const data = block.data as BlogGalleryData}
|
|
864
|
+
<div class="flex flex-col gap-2">
|
|
865
|
+
<div class="flex flex-wrap gap-2">
|
|
866
|
+
<Select
|
|
867
|
+
value={String(data.columns ?? 3)}
|
|
868
|
+
options={[
|
|
869
|
+
{ value: '2', label: '2 cols' },
|
|
870
|
+
{ value: '3', label: '3 cols' },
|
|
871
|
+
{ value: '4', label: '4 cols' }
|
|
872
|
+
]}
|
|
873
|
+
onchange={(v) =>
|
|
874
|
+
updateBlock(block.id, {
|
|
875
|
+
...data,
|
|
876
|
+
columns: Number(v) as BlogGalleryData['columns']
|
|
877
|
+
})}
|
|
878
|
+
class="w-28"
|
|
879
|
+
/>
|
|
880
|
+
<Select
|
|
881
|
+
value={data.gap ?? 'md'}
|
|
882
|
+
options={[
|
|
883
|
+
{ value: 'sm', label: 'Gap S' },
|
|
884
|
+
{ value: 'md', label: 'Gap M' },
|
|
885
|
+
{ value: 'lg', label: 'Gap L' }
|
|
886
|
+
]}
|
|
887
|
+
onchange={(v) =>
|
|
888
|
+
updateBlock(block.id, {
|
|
889
|
+
...data,
|
|
890
|
+
gap: v as BlogGalleryData['gap']
|
|
891
|
+
})}
|
|
892
|
+
class="w-28"
|
|
893
|
+
/>
|
|
894
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
895
|
+
<input
|
|
896
|
+
type="checkbox"
|
|
897
|
+
checked={data.rounded !== false}
|
|
898
|
+
onchange={(e) =>
|
|
899
|
+
updateBlock(block.id, {
|
|
900
|
+
...data,
|
|
901
|
+
rounded: (e.currentTarget as HTMLInputElement).checked
|
|
902
|
+
})}
|
|
903
|
+
/>
|
|
904
|
+
Rounded
|
|
905
|
+
</label>
|
|
906
|
+
</div>
|
|
907
|
+
<Textarea
|
|
908
|
+
value={data.images.map((img) => img.src).join('\n')}
|
|
909
|
+
rows={4}
|
|
910
|
+
placeholder="One image URL per line"
|
|
911
|
+
oninput={(e) =>
|
|
912
|
+
updateBlock(block.id, {
|
|
913
|
+
...data,
|
|
914
|
+
images: (e.currentTarget as HTMLTextAreaElement).value
|
|
915
|
+
.split('\n')
|
|
916
|
+
.map((src) => ({ src: src.trim(), alt: '' }))
|
|
917
|
+
.filter((img) => img.src.length >= 0)
|
|
918
|
+
})}
|
|
919
|
+
/>
|
|
920
|
+
</div>
|
|
921
|
+
{:else if block.type === 'table'}
|
|
922
|
+
{@const data = block.data as BlogTableData}
|
|
923
|
+
<div class="flex flex-col gap-2">
|
|
924
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
925
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
926
|
+
<input
|
|
927
|
+
type="checkbox"
|
|
928
|
+
checked={data.striped !== false}
|
|
929
|
+
onchange={(e) =>
|
|
930
|
+
updateBlock(block.id, {
|
|
931
|
+
...data,
|
|
932
|
+
striped: (e.currentTarget as HTMLInputElement).checked
|
|
933
|
+
})}
|
|
934
|
+
/>
|
|
935
|
+
Striped
|
|
936
|
+
</label>
|
|
937
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
938
|
+
<input
|
|
939
|
+
type="checkbox"
|
|
940
|
+
checked={!!data.compact}
|
|
941
|
+
onchange={(e) =>
|
|
942
|
+
updateBlock(block.id, {
|
|
943
|
+
...data,
|
|
944
|
+
compact: (e.currentTarget as HTMLInputElement).checked
|
|
945
|
+
})}
|
|
946
|
+
/>
|
|
947
|
+
Compact
|
|
948
|
+
</label>
|
|
949
|
+
<Input
|
|
950
|
+
value={data.caption ?? ''}
|
|
951
|
+
placeholder="Caption"
|
|
952
|
+
class="flex-1"
|
|
953
|
+
oninput={(e) =>
|
|
954
|
+
updateBlock(block.id, {
|
|
955
|
+
...data,
|
|
956
|
+
caption: (e.currentTarget as HTMLInputElement).value
|
|
957
|
+
})}
|
|
958
|
+
/>
|
|
959
|
+
</div>
|
|
960
|
+
<Input
|
|
961
|
+
value={data.headers.join(' | ')}
|
|
962
|
+
placeholder="Headers separated by |"
|
|
963
|
+
oninput={(e) =>
|
|
964
|
+
updateBlock(block.id, {
|
|
965
|
+
...data,
|
|
966
|
+
headers: (e.currentTarget as HTMLInputElement).value
|
|
967
|
+
.split('|')
|
|
968
|
+
.map((h) => h.trim())
|
|
969
|
+
})}
|
|
970
|
+
/>
|
|
971
|
+
<Textarea
|
|
972
|
+
value={data.rows.map((r) => r.join(' | ')).join('\n')}
|
|
973
|
+
rows={4}
|
|
974
|
+
placeholder={'Rows: cell | cell\none row per line'}
|
|
975
|
+
oninput={(e) =>
|
|
976
|
+
updateBlock(block.id, {
|
|
977
|
+
...data,
|
|
978
|
+
rows: (e.currentTarget as HTMLTextAreaElement).value
|
|
979
|
+
.split('\n')
|
|
980
|
+
.map((line) => line.split('|').map((c) => c.trim()))
|
|
981
|
+
})}
|
|
982
|
+
/>
|
|
983
|
+
</div>
|
|
984
|
+
{:else if block.type === 'cta'}
|
|
985
|
+
{@const data = block.data as BlogCtaData}
|
|
986
|
+
<div class="grid gap-2 sm:grid-cols-2">
|
|
987
|
+
<Input
|
|
988
|
+
value={data.label}
|
|
989
|
+
placeholder="Button label"
|
|
990
|
+
oninput={(e) =>
|
|
991
|
+
updateBlock(block.id, {
|
|
992
|
+
...data,
|
|
993
|
+
label: (e.currentTarget as HTMLInputElement).value
|
|
994
|
+
})}
|
|
995
|
+
/>
|
|
996
|
+
<Input
|
|
997
|
+
value={data.href ?? ''}
|
|
998
|
+
placeholder="Href"
|
|
999
|
+
oninput={(e) =>
|
|
1000
|
+
updateBlock(block.id, {
|
|
1001
|
+
...data,
|
|
1002
|
+
href: (e.currentTarget as HTMLInputElement).value
|
|
1003
|
+
})}
|
|
1004
|
+
/>
|
|
1005
|
+
<Select
|
|
1006
|
+
value={data.variant ?? 'primary'}
|
|
1007
|
+
options={[
|
|
1008
|
+
{ value: 'primary', label: 'Primary' },
|
|
1009
|
+
{ value: 'secondary', label: 'Secondary' },
|
|
1010
|
+
{ value: 'ghost', label: 'Ghost' },
|
|
1011
|
+
{ value: 'outline', label: 'Outline' }
|
|
1012
|
+
]}
|
|
1013
|
+
onchange={(v) =>
|
|
1014
|
+
updateBlock(block.id, {
|
|
1015
|
+
...data,
|
|
1016
|
+
variant: v as BlogCtaData['variant']
|
|
1017
|
+
})}
|
|
1018
|
+
/>
|
|
1019
|
+
<Select
|
|
1020
|
+
value={data.align ?? 'center'}
|
|
1021
|
+
options={ALIGN_OPTS}
|
|
1022
|
+
onchange={(v) => updateBlock(block.id, { ...data, align: v as BlogAlign })}
|
|
1023
|
+
/>
|
|
1024
|
+
<Input
|
|
1025
|
+
value={data.subtitle ?? ''}
|
|
1026
|
+
placeholder="Subtitle"
|
|
1027
|
+
class="sm:col-span-2"
|
|
1028
|
+
oninput={(e) =>
|
|
1029
|
+
updateBlock(block.id, {
|
|
1030
|
+
...data,
|
|
1031
|
+
subtitle: (e.currentTarget as HTMLInputElement).value
|
|
1032
|
+
})}
|
|
1033
|
+
/>
|
|
1034
|
+
<label class="flex items-center gap-1.5 text-xs text-muted">
|
|
1035
|
+
<input
|
|
1036
|
+
type="checkbox"
|
|
1037
|
+
checked={!!data.openInNewTab}
|
|
1038
|
+
onchange={(e) =>
|
|
1039
|
+
updateBlock(block.id, {
|
|
1040
|
+
...data,
|
|
1041
|
+
openInNewTab: (e.currentTarget as HTMLInputElement).checked
|
|
1042
|
+
})}
|
|
1043
|
+
/>
|
|
1044
|
+
Open in new tab
|
|
1045
|
+
</label>
|
|
1046
|
+
</div>
|
|
1047
|
+
{:else if block.type === 'spacer'}
|
|
1048
|
+
{@const data = block.data as BlogSpacerData}
|
|
1049
|
+
<Select
|
|
1050
|
+
value={data.size ?? 'md'}
|
|
1051
|
+
options={[
|
|
1052
|
+
{ value: 'xs', label: 'XS' },
|
|
1053
|
+
{ value: 'sm', label: 'S' },
|
|
1054
|
+
{ value: 'md', label: 'M' },
|
|
1055
|
+
{ value: 'lg', label: 'L' },
|
|
1056
|
+
{ value: 'xl', label: 'XL' }
|
|
1057
|
+
]}
|
|
1058
|
+
onchange={(v) =>
|
|
1059
|
+
updateBlock(block.id, {
|
|
1060
|
+
...data,
|
|
1061
|
+
size: v as BlogSpacerData['size']
|
|
1062
|
+
})}
|
|
1063
|
+
class="w-32"
|
|
1064
|
+
/>
|
|
1065
|
+
{:else if block.type === 'html'}
|
|
1066
|
+
{@const data = block.data as BlogHtmlData}
|
|
1067
|
+
<Textarea
|
|
1068
|
+
value={data.html}
|
|
1069
|
+
rows={5}
|
|
1070
|
+
class="font-mono text-xs"
|
|
1071
|
+
placeholder="<div>...</div>"
|
|
1072
|
+
oninput={(e) =>
|
|
1073
|
+
updateBlock(block.id, {
|
|
1074
|
+
...data,
|
|
1075
|
+
html: (e.currentTarget as HTMLTextAreaElement).value
|
|
1076
|
+
})}
|
|
1077
|
+
/>
|
|
1078
|
+
{:else if block.type === 'component'}
|
|
1079
|
+
{@const data = block.data as BlogComponentData}
|
|
1080
|
+
{@const reg = getBlogComponent(data.componentId)}
|
|
1081
|
+
<div class="flex flex-col gap-2">
|
|
1082
|
+
<p class="text-xs text-muted">
|
|
1083
|
+
Component: <code>{data.componentId}</code>
|
|
1084
|
+
{#if reg?.description}
|
|
1085
|
+
— {reg.description}
|
|
1086
|
+
{/if}
|
|
1087
|
+
</p>
|
|
1088
|
+
{#if reg?.propFields?.length}
|
|
1089
|
+
<div class="grid gap-2 sm:grid-cols-2">
|
|
1090
|
+
{#each reg.propFields as field (field.key)}
|
|
1091
|
+
{#if field.type === 'boolean'}
|
|
1092
|
+
<label class="flex items-center gap-1.5 text-xs text-muted sm:col-span-2">
|
|
1093
|
+
<input
|
|
1094
|
+
type="checkbox"
|
|
1095
|
+
checked={Boolean(data.props?.[field.key])}
|
|
1096
|
+
onchange={(e) =>
|
|
1097
|
+
updateComponentProp(
|
|
1098
|
+
block.id,
|
|
1099
|
+
data,
|
|
1100
|
+
field.key,
|
|
1101
|
+
(e.currentTarget as HTMLInputElement).checked
|
|
1102
|
+
)}
|
|
1103
|
+
/>
|
|
1104
|
+
{field.label}
|
|
1105
|
+
</label>
|
|
1106
|
+
{:else if field.type === 'select' && field.options}
|
|
1107
|
+
<div class="flex flex-col gap-1">
|
|
1108
|
+
<span class="text-[11px] text-muted">{field.label}</span>
|
|
1109
|
+
<Select
|
|
1110
|
+
value={String(data.props?.[field.key] ?? '')}
|
|
1111
|
+
options={field.options}
|
|
1112
|
+
onchange={(v) => updateComponentProp(block.id, data, field.key, v)}
|
|
1113
|
+
/>
|
|
1114
|
+
</div>
|
|
1115
|
+
{:else if field.type === 'textarea'}
|
|
1116
|
+
<div class="flex flex-col gap-1 sm:col-span-2">
|
|
1117
|
+
<span class="text-[11px] text-muted">{field.label}</span>
|
|
1118
|
+
<Textarea
|
|
1119
|
+
value={String(data.props?.[field.key] ?? '')}
|
|
1120
|
+
rows={3}
|
|
1121
|
+
placeholder={field.placeholder}
|
|
1122
|
+
oninput={(e) =>
|
|
1123
|
+
updateComponentProp(
|
|
1124
|
+
block.id,
|
|
1125
|
+
data,
|
|
1126
|
+
field.key,
|
|
1127
|
+
(e.currentTarget as HTMLTextAreaElement).value
|
|
1128
|
+
)}
|
|
1129
|
+
/>
|
|
1130
|
+
</div>
|
|
1131
|
+
{:else if field.type === 'number'}
|
|
1132
|
+
<div class="flex flex-col gap-1">
|
|
1133
|
+
<span class="text-[11px] text-muted">{field.label}</span>
|
|
1134
|
+
<Input
|
|
1135
|
+
type="number"
|
|
1136
|
+
value={String(data.props?.[field.key] ?? '')}
|
|
1137
|
+
placeholder={field.placeholder}
|
|
1138
|
+
oninput={(e) =>
|
|
1139
|
+
updateComponentProp(
|
|
1140
|
+
block.id,
|
|
1141
|
+
data,
|
|
1142
|
+
field.key,
|
|
1143
|
+
Number((e.currentTarget as HTMLInputElement).value)
|
|
1144
|
+
)}
|
|
1145
|
+
/>
|
|
1146
|
+
</div>
|
|
1147
|
+
{:else}
|
|
1148
|
+
<div class="flex flex-col gap-1">
|
|
1149
|
+
<span class="text-[11px] text-muted">{field.label}</span>
|
|
1150
|
+
{#if field.type === 'color'}
|
|
1151
|
+
<input
|
|
1152
|
+
type="color"
|
|
1153
|
+
class="h-9 w-full cursor-pointer rounded-md border border-border bg-surface"
|
|
1154
|
+
value={String(data.props?.[field.key] ?? '#0ea5e9')}
|
|
1155
|
+
oninput={(e) =>
|
|
1156
|
+
updateComponentProp(
|
|
1157
|
+
block.id,
|
|
1158
|
+
data,
|
|
1159
|
+
field.key,
|
|
1160
|
+
(e.currentTarget as HTMLInputElement).value
|
|
1161
|
+
)}
|
|
1162
|
+
/>
|
|
1163
|
+
{:else}
|
|
1164
|
+
<Input
|
|
1165
|
+
value={String(data.props?.[field.key] ?? '')}
|
|
1166
|
+
placeholder={field.placeholder}
|
|
1167
|
+
oninput={(e) =>
|
|
1168
|
+
updateComponentProp(
|
|
1169
|
+
block.id,
|
|
1170
|
+
data,
|
|
1171
|
+
field.key,
|
|
1172
|
+
(e.currentTarget as HTMLInputElement).value
|
|
1173
|
+
)}
|
|
1174
|
+
/>
|
|
1175
|
+
{/if}
|
|
1176
|
+
</div>
|
|
1177
|
+
{/if}
|
|
1178
|
+
{/each}
|
|
1179
|
+
</div>
|
|
1180
|
+
{:else}
|
|
1181
|
+
<Textarea
|
|
1182
|
+
value={JSON.stringify(data.props ?? {}, null, 2)}
|
|
1183
|
+
rows={4}
|
|
1184
|
+
class="font-mono text-xs"
|
|
1185
|
+
oninput={(e) => {
|
|
1186
|
+
try {
|
|
1187
|
+
const props = JSON.parse((e.currentTarget as HTMLTextAreaElement).value);
|
|
1188
|
+
updateBlock(block.id, { ...data, props });
|
|
1189
|
+
} catch {
|
|
1190
|
+
/* ignore invalid JSON while typing */
|
|
1191
|
+
}
|
|
1192
|
+
}}
|
|
1193
|
+
/>
|
|
1194
|
+
{/if}
|
|
1195
|
+
</div>
|
|
1196
|
+
{/if}
|
|
1197
|
+
</li>
|
|
1198
|
+
{/each}
|
|
1199
|
+
</ul>
|
|
1200
|
+
{/if}
|
|
1201
|
+
|
|
1202
|
+
{#if showJson}
|
|
1203
|
+
<div class="border-t border-border pt-3">
|
|
1204
|
+
<p class="mb-2 text-xs font-semibold uppercase tracking-wide text-muted">JSON</p>
|
|
1205
|
+
<JSONViewer data={value} />
|
|
1206
|
+
</div>
|
|
1207
|
+
{/if}
|
|
1208
|
+
</div>
|