@hyperframes/studio 0.8.50 → 0.8.53-desktop.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/assets/{hyperframes-player-CxxDxHTW.js → hyperframes-player-PTEnAHhg.js} +3 -3
- package/dist/assets/{index-DUAIWxkI.js → index--myXp8ui.js} +1 -1
- package/dist/assets/{index-Dt3qBI-9.js → index-BjslOS9g.js} +1 -1
- package/dist/assets/index-BnXZuIJD.css +1 -0
- package/dist/assets/index-CNyviK_l.js +390 -0
- package/dist/index.css +29 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +825 -24
- package/dist/index.html +2 -2
- package/dist/index.js +8911 -9853
- package/dist/index.js.map +1 -1
- package/dist/styles/tailwind-preset.js.map +1 -1
- package/package.json +13 -12
- package/src/App.tsx +145 -163
- package/src/captions/components/CaptionAnimationPanel.tsx +4 -4
- package/src/captions/components/CaptionOverlay.sender.test.tsx +52 -0
- package/src/captions/components/CaptionOverlay.tsx +8 -4
- package/src/captions/components/CaptionOverlayUtils.ts +2 -3
- package/src/captions/components/CaptionPropertyPanel.tsx +3 -3
- package/src/captions/components/CaptionTimeline.tsx +1 -1
- package/src/captions/components/shared.tsx +2 -2
- package/src/components/AskAgentModal.tsx +5 -5
- package/src/components/EditorShell.selectionSync.test.tsx +9 -4
- package/src/components/EditorShell.tsx +59 -62
- package/src/components/ExternalFileConflictBanner.tsx +16 -16
- package/src/components/LintModal.tsx +6 -16
- package/src/components/MediaPreview.tsx +2 -2
- package/src/components/RightPanelTabs.test.tsx +151 -0
- package/src/components/RightPanelTabs.tsx +59 -0
- package/src/components/SaveQueuePausedBanner.tsx +2 -2
- package/src/components/StudioHeader.dom.test.tsx +181 -0
- package/src/components/StudioHeader.test.ts +0 -12
- package/src/components/StudioHeader.tsx +118 -221
- package/src/components/StudioLeftPanels.tsx +202 -0
- package/src/components/StudioOverlays.tsx +1 -1
- package/src/components/{StudioRightPanel.tsx → StudioRightPanels.tsx} +57 -194
- package/src/components/{StudioRightPanel.types.ts → StudioRightPanels.types.ts} +4 -3
- package/src/components/StudioToast.tsx +2 -2
- package/src/components/TimelineHistoryButtons.dom.test.tsx +117 -0
- package/src/components/TimelineHistoryButtons.tsx +54 -0
- package/src/components/TimelineToolbar.test.tsx +8 -0
- package/src/components/TimelineToolbar.tsx +8 -12
- package/src/components/dock/Dock.test.tsx +274 -0
- package/src/components/dock/Dock.tsx +291 -0
- package/src/components/dock/dock.css +28 -0
- package/src/components/dock/dockAccessibility.test.ts +166 -0
- package/src/components/dock/dockAccessibility.ts +98 -0
- package/src/components/dock/dockLayout.test.ts +134 -0
- package/src/components/dock/dockLayout.ts +105 -0
- package/src/components/dock/dockLayoutSchema.ts +66 -0
- package/src/components/dock/dockLayoutStore.test.ts +28 -0
- package/src/components/dock/dockLayoutStore.ts +108 -0
- package/src/components/dock/dockTestHarness.ts +11 -0
- package/src/components/dock/panelRegistry.ts +67 -0
- package/src/components/editor/AnimationCard.tsx +4 -4
- package/src/components/editor/AnimationCardParts.tsx +6 -6
- package/src/components/editor/BlockParamsPanel.tsx +4 -4
- package/src/components/editor/BorderRadiusEditor.tsx +1 -1
- package/src/components/editor/CanvasContextMenu.tsx +1 -1
- package/src/components/editor/ComputedTweenNotice.tsx +1 -1
- package/src/components/editor/DomEditOverlay.tsx +1 -1
- package/src/components/editor/EaseCurveSection.tsx +1 -1
- package/src/components/editor/EaseParamFields.tsx +5 -5
- package/src/components/editor/FileTree.tsx +4 -4
- package/src/components/editor/FileTreeIcons.tsx +1 -1
- package/src/components/editor/FileTreeNodes.tsx +13 -13
- package/src/components/editor/InlineTextToolbar.tsx +1 -1
- package/src/components/editor/InspectorHeaderActions.tsx +3 -3
- package/src/components/editor/KeyframeDiamond.tsx +1 -1
- package/src/components/editor/KeyframeEaseList.tsx +1 -1
- package/src/components/editor/LayersPanel.test.ts +97 -1
- package/src/components/editor/LayersPanel.tsx +7 -5
- package/src/components/editor/MarqueeOverlay.tsx +1 -1
- package/src/components/editor/OffCanvasIndicators.tsx +1 -1
- package/src/components/editor/PreviewGuides.tsx +1 -1
- package/src/components/editor/PromotableControl.tsx +2 -2
- package/src/components/editor/PropertyPanelEmptyState.tsx +7 -7
- package/src/components/editor/PropertyPanelFlatHeader.tsx +2 -2
- package/src/components/editor/SnapToolbar.test.tsx +0 -3
- package/src/components/editor/SnapToolbar.tsx +2 -2
- package/src/components/editor/TimelineFxPopover.tsx +1 -1
- package/src/components/editor/TopologyLens.test.tsx +28 -0
- package/src/components/editor/TopologyLens.tsx +7 -5
- package/src/components/editor/Transform3DCube.tsx +2 -2
- package/src/components/editor/audioFxRevealTarget.ts +1 -0
- package/src/components/editor/domEditing.test.ts +1 -1
- package/src/components/editor/domEditingAgentPrompt.test.ts +8 -6
- package/src/components/editor/domEditingAgentPrompt.ts +4 -3
- package/src/components/editor/propertyPanelColor.tsx +11 -11
- package/src/components/editor/propertyPanelColorCurveGraph.tsx +1 -1
- package/src/components/editor/propertyPanelColorGradingControls.tsx +7 -9
- package/src/components/editor/propertyPanelColorGradingSection.tsx +6 -6
- package/src/components/editor/propertyPanelColorGradingSlider.tsx +5 -5
- package/src/components/editor/propertyPanelColorWheels.tsx +1 -1
- package/src/components/editor/propertyPanelCommitField.tsx +1 -1
- package/src/components/editor/propertyPanelFill.tsx +4 -4
- package/src/components/editor/propertyPanelFlatColorGradingAccessory.tsx +3 -3
- package/src/components/editor/propertyPanelFlatColorGradingSection.tsx +7 -7
- package/src/components/editor/propertyPanelFlatEffectsSection.tsx +4 -4
- package/src/components/editor/propertyPanelFlatMediaSection.tsx +3 -3
- package/src/components/editor/propertyPanelFlatOverlaysSection.tsx +1 -1
- package/src/components/editor/propertyPanelFlatPrimitives.tsx +10 -10
- package/src/components/editor/propertyPanelFlatSelectRow.tsx +3 -3
- package/src/components/editor/propertyPanelFlatTextSection.test.tsx +8 -9
- package/src/components/editor/propertyPanelFlatTextSection.tsx +5 -5
- package/src/components/editor/propertyPanelFlatToggle.tsx +1 -1
- package/src/components/editor/propertyPanelFont.tsx +5 -5
- package/src/components/editor/propertyPanelFxCarveModule.tsx +1 -1
- package/src/components/editor/propertyPanelFxControls.test.tsx +1 -1
- package/src/components/editor/propertyPanelFxControls.tsx +6 -6
- package/src/components/editor/propertyPanelFxEqModule.tsx +2 -2
- package/src/components/editor/propertyPanelFxPresetStyle.ts +2 -2
- package/src/components/editor/propertyPanelGradingNumberField.tsx +1 -1
- package/src/components/editor/propertyPanelMediaSection.tsx +1 -1
- package/src/components/editor/propertyPanelPrimitives.tsx +7 -7
- package/src/components/editor/propertyPanelSections.tsx +8 -8
- package/src/components/editor/useColorGradingController.test.ts +38 -0
- package/src/components/editor/useColorGradingController.ts +9 -1
- package/src/components/editor/useColorGradingPreviews.test.ts +76 -0
- package/src/components/editor/useColorGradingPreviews.ts +11 -1
- package/src/components/editor/usePreviewCompositionRect.test.tsx +95 -0
- package/src/components/editor/usePreviewCompositionRect.ts +21 -0
- package/src/components/feedback/StudioFeedbackCard.tsx +7 -7
- package/src/components/feedback/feedbackTrigger.ts +0 -1
- package/src/components/nle/AssetPreviewOverlay.tsx +6 -2
- package/src/components/nle/CompositionBreadcrumb.tsx +3 -3
- package/src/components/nle/NLEContext.tsx +0 -43
- package/src/components/nle/NLEPreview.tsx +3 -3
- package/src/components/nle/PreviewOverlays.tsx +6 -6
- package/src/components/nle/PreviewPane.tsx +3 -3
- package/src/components/nle/TimelinePane.tsx +53 -67
- package/src/components/panels/SlideshowPanel.tsx +3 -3
- package/src/components/panels/SlideshowSubPanels.tsx +20 -17
- package/src/components/panels/VariablesBindElement.tsx +2 -2
- package/src/components/panels/VariablesDeclarationForm.tsx +2 -2
- package/src/components/panels/VariablesOtherCompositions.tsx +1 -1
- package/src/components/panels/VariablesPanel.tsx +4 -4
- package/src/components/panels/VariablesValueControls.tsx +2 -2
- package/src/components/pointerTargetSize.test.tsx +8 -0
- package/src/components/renders/FfmpegRequiredNotice.tsx +5 -5
- package/src/components/renders/RenderQueue.test.tsx +7 -0
- package/src/components/renders/RenderQueue.tsx +7 -7
- package/src/components/renders/RenderQueueItem.tsx +6 -6
- package/src/components/renders/RenderQueuePanel.tsx +1 -1
- package/src/components/sidebar/AssetCard.tsx +8 -8
- package/src/components/sidebar/AssetContextMenu.tsx +8 -8
- package/src/components/sidebar/AssetsTab.tsx +2 -2
- package/src/components/sidebar/AudioRow.tsx +6 -6
- package/src/components/sidebar/BlocksTab.tsx +6 -6
- package/src/components/sidebar/{LeftSidebar.masterComposition.test.tsx → CompositionsPanel.masterComposition.test.tsx} +6 -9
- package/src/components/sidebar/CompositionsPanel.tsx +15 -0
- package/src/components/sidebar/CompositionsTab.tsx +5 -5
- package/src/components/sidebar/GlobalAssetsView.tsx +1 -1
- package/src/components/sidebar/PromptPreviewModal.tsx +3 -3
- package/src/components/sidebar/SidebarLintButton.test.tsx +53 -0
- package/src/components/sidebar/SidebarLintButton.tsx +50 -0
- package/src/components/timelineToolbarStyles.ts +5 -0
- package/src/components/ui/Button.test.tsx +252 -0
- package/src/components/ui/Button.tsx +89 -126
- package/src/components/ui/IconButton.tsx +38 -0
- package/src/components/ui/Input.tsx +115 -0
- package/src/components/ui/Menu.test.tsx +374 -0
- package/src/components/ui/Menu.tsx +213 -0
- package/src/components/ui/NumberField.tsx +122 -0
- package/src/components/ui/Popover.tsx +74 -0
- package/src/components/ui/SearchInput.tsx +2 -2
- package/src/components/ui/Select.tsx +100 -0
- package/src/components/ui/Slider.tsx +153 -0
- package/src/components/ui/Tabs.test.tsx +98 -0
- package/src/components/ui/Tabs.tsx +71 -0
- package/src/components/ui/Toggle.tsx +63 -0
- package/src/components/ui/Tooltip.test.tsx +110 -0
- package/src/components/ui/Tooltip.tsx +38 -112
- package/src/components/ui/cn.test.ts +30 -0
- package/src/components/ui/cn.ts +25 -0
- package/src/components/ui/index.ts +29 -2
- package/src/components/ui/mountHost.testHelpers.ts +24 -0
- package/src/components/ui/valueControls.test.tsx +524 -0
- package/src/contexts/PanelLayoutContext.tsx +3 -57
- package/src/hooks/appHotkeysDispatch.ts +3 -4
- package/src/hooks/timelineEditPermission.ts +31 -0
- package/src/hooks/useAppHotkeys.previewForwarding.test.tsx +0 -2
- package/src/hooks/useAppHotkeys.test.ts +0 -1
- package/src/hooks/useAppHotkeys.textEditing.test.tsx +0 -3
- package/src/hooks/useAppHotkeys.ts +21 -84
- package/src/hooks/useCaptionDetection.sender.test.tsx +46 -0
- package/src/hooks/useCaptionDetection.ts +3 -1
- package/src/hooks/useDomEditPreviewSync.ts +4 -6
- package/src/hooks/useDomEditSession.ts +0 -7
- package/src/hooks/useDomEditWiring.ts +4 -9
- package/src/hooks/useEditHistoryActions.test.tsx +90 -0
- package/src/hooks/useEditHistoryActions.ts +106 -0
- package/src/hooks/useFileManager.ts +21 -123
- package/src/hooks/useLintModal.test.tsx +65 -0
- package/src/hooks/useLintModal.ts +3 -0
- package/src/hooks/usePanelLayout.test.ts +108 -296
- package/src/hooks/usePanelLayout.ts +50 -255
- package/src/hooks/usePersistentEditHistory.ts +1 -1
- package/src/hooks/useProjectFileWriter.ts +150 -0
- package/src/hooks/useRightPanelIntents.test.ts +181 -0
- package/src/hooks/useRightPanelIntents.ts +63 -0
- package/src/hooks/useSdkSession.lifecycle.test.tsx +49 -4
- package/src/hooks/useSdkSession.ts +43 -10
- package/src/hooks/useServerConnection.hashProject.test.tsx +94 -0
- package/src/hooks/useServerConnection.ts +43 -10
- package/src/hooks/useSlideshowTabState.test.ts +9 -31
- package/src/hooks/useSlideshowTabState.ts +6 -19
- package/src/hooks/useStudioContextValue.test.ts +6 -18
- package/src/hooks/useStudioContextValue.ts +5 -26
- package/src/hooks/useTimelineAssetDropOps.test.tsx +41 -1
- package/src/hooks/useTimelineAssetDropOps.ts +52 -11
- package/src/hooks/useTimelineDeleteOps.test.tsx +111 -0
- package/src/hooks/useTimelineEditing.test.tsx +322 -3
- package/src/hooks/useTimelineEditing.ts +103 -16
- package/src/hooks/useTimelineEditingTypes.ts +3 -0
- package/src/hooks/useTrackPendingTimelineEdit.test.tsx +62 -0
- package/src/hooks/useTrackPendingTimelineEdit.ts +22 -0
- package/src/hostMount.test.tsx +222 -0
- package/src/index.ts +87 -0
- package/src/main.tsx +9 -3
- package/src/player/components/AudioWaveform.tsx +1 -1
- package/src/player/components/AutomationSelectionMenu.tsx +3 -3
- package/src/player/components/ClipContextMenu.tsx +3 -3
- package/src/player/components/CompositionThumbnail.test.ts +0 -3
- package/src/player/components/CompositionThumbnail.tsx +3 -4
- package/src/player/components/EditModal.tsx +1 -1
- package/src/player/components/ImageThumbnail.tsx +1 -1
- package/src/player/components/KeyframeDiamondContextMenu.tsx +4 -4
- package/src/player/components/LayerDisclosureRow.tsx +2 -2
- package/src/player/components/PlayerControls.tsx +1 -1
- package/src/player/components/ShortcutsPanel.tsx +9 -9
- package/src/player/components/SpeedMenu.tsx +3 -5
- package/src/player/components/Timeline.tsx +3 -2
- package/src/player/components/TimelineCanvas.tsx +21 -14
- package/src/player/components/TimelineClip.tsx +0 -1
- package/src/player/components/TimelineDiamondConnectors.tsx +1 -1
- package/src/player/components/TimelineEmptyState.tsx +5 -5
- package/src/player/components/TimelineFxButton.tsx +6 -6
- package/src/player/components/TimelineGroupHeader.tsx +5 -5
- package/src/player/components/TimelineGroupLaneLabels.tsx +1 -1
- package/src/player/components/TimelineGroupRow.tsx +1 -1
- package/src/player/components/TimelineLanes.test.tsx +32 -0
- package/src/player/components/TimelineLanes.tsx +2 -5
- package/src/player/components/TimelineLayerGroupHeader.tsx +2 -2
- package/src/player/components/TimelineRuler.tsx +1 -1
- package/src/player/components/TimelineShortcutHint.tsx +1 -1
- package/src/player/components/TimelineTrackHeader.test.tsx +26 -5
- package/src/player/components/TimelineTrackHeader.tsx +2 -2
- package/src/player/components/TimelineTrackPlainHeader.tsx +3 -3
- package/src/player/components/TimelineTypes.ts +2 -1
- package/src/player/components/TrackGapContextMenu.tsx +1 -1
- package/src/player/components/VideoThumbnail.tsx +4 -2
- package/src/player/components/VolumeControl.tsx +2 -2
- package/src/player/components/timelineCallbacks.ts +8 -8
- package/src/player/components/timelineClipDragPreview.ts +51 -27
- package/src/player/components/timelineClipDragTypes.ts +3 -0
- package/src/player/components/timelineDragDrop.test.tsx +61 -1
- package/src/player/components/timelineDragDrop.ts +57 -15
- package/src/player/components/timelineLaneProps.ts +3 -0
- package/src/player/components/timelineSnapping.test.ts +27 -0
- package/src/player/components/timelineSnapping.ts +14 -1
- package/src/player/components/timelineTheme.test.ts +4 -4
- package/src/player/components/timelineTheme.ts +30 -30
- package/src/player/components/trackHeaderLabelRows.tsx +4 -4
- package/src/player/components/useTimelineClipDrag.resize.test.tsx +136 -2
- package/src/player/components/useTimelineClipDrag.ts +30 -3
- package/src/player/lib/describeClips.ts +3 -54
- package/src/player/lib/playbackShortcuts.ts +2 -0
- package/src/player/lib/timelinePerformanceDiagnostics.test.ts +3 -2
- package/src/player/lib/timelinePerformanceDiagnostics.ts +1 -1
- package/src/player/store/previewIframeStore.notify.test.tsx +75 -0
- package/src/player/store/previewIframeStore.test.tsx +29 -0
- package/src/player/store/previewIframeStore.ts +25 -0
- package/src/renderQueueExports.test.tsx +58 -0
- package/src/styles/classCandidates.test.ts +105 -0
- package/src/styles/classCandidates.ts +281 -0
- package/src/styles/hex-baseline.json +84 -0
- package/src/styles/hexRatchet.test.ts +201 -0
- package/src/styles/iconTokens.ts +20 -0
- package/src/styles/palette-reset.css +6 -0
- package/src/styles/studio.css +24 -21
- package/src/styles/styleSources.test.ts +20 -0
- package/src/styles/styleSources.ts +47 -0
- package/src/styles/tailwind-preset.shared.js +3 -0
- package/src/styles/theme.css +270 -0
- package/src/styles/theme.test.ts +183 -0
- package/src/styles/tokenGate.test.ts +109 -0
- package/src/utils/sourcePatcher.ts +1 -1
- package/src/utils/studioHelpers.test.ts +18 -0
- package/src/utils/studioHelpers.ts +11 -8
- package/src/utils/studioUiPreferences.test.ts +10 -16
- package/src/utils/studioUiPreferences.ts +7 -16
- package/src/utils/timelineDropTrackInsert.test.ts +134 -0
- package/src/utils/timelineDropTrackInsert.ts +83 -0
- package/src/utils/typingTarget.ts +4 -0
- package/dist/assets/index-n2ml4tUn.js +0 -442
- package/dist/assets/index-pO6p0H27.css +0 -1
- package/src/components/PanelTabButton.tsx +0 -31
- package/src/components/StudioLeftSidebar.tsx +0 -204
- package/src/components/nle/TimelineResizeDivider.tsx +0 -101
- package/src/components/sidebar/LeftSidebar.storage.test.ts +0 -28
- package/src/components/sidebar/LeftSidebar.tsx +0 -334
- package/src/components/storyboard/AgentChatMessageButton.test.tsx +0 -47
- package/src/components/storyboard/AgentChatMessageButton.tsx +0 -45
- package/src/components/storyboard/FramePoster.test.tsx +0 -61
- package/src/components/storyboard/FramePoster.tsx +0 -86
- package/src/components/storyboard/StoryboardDirection.tsx +0 -45
- package/src/components/storyboard/StoryboardFrameFocus.tsx +0 -412
- package/src/components/storyboard/StoryboardFrameTile.tsx +0 -117
- package/src/components/storyboard/StoryboardGrid.tsx +0 -55
- package/src/components/storyboard/StoryboardLoaded.tsx +0 -307
- package/src/components/storyboard/StoryboardReviewGuide.tsx +0 -300
- package/src/components/storyboard/StoryboardScriptPanel.tsx +0 -26
- package/src/components/storyboard/StoryboardSourceEditor.tsx +0 -231
- package/src/components/storyboard/StoryboardStatusLegend.tsx +0 -21
- package/src/components/storyboard/StoryboardView.tsx +0 -169
- package/src/components/storyboard/StoryboardViewModeGuard.test.tsx +0 -187
- package/src/components/storyboard/frameComments.test.ts +0 -95
- package/src/components/storyboard/frameComments.ts +0 -115
- package/src/components/storyboard/frameStatus.ts +0 -36
- package/src/components/storyboard/storyboardReviewStage.test.ts +0 -40
- package/src/components/storyboard/storyboardReviewStage.ts +0 -45
- package/src/components/storyboard/useFrameComments.ts +0 -98
- package/src/contexts/ViewModeContext.tsx +0 -142
- package/src/hooks/useInspectorSplitResize.ts +0 -51
- package/src/hooks/useProjectSignaturePoll.test.tsx +0 -135
- package/src/hooks/useProjectSignaturePoll.ts +0 -68
- package/src/hooks/useStoryboard.ts +0 -99
- package/src/utils/fitPanels.test.ts +0 -164
- package/src/utils/fitPanels.ts +0 -151
|
@@ -221,9 +221,8 @@ export function registerCaptionIframe(ref: React.RefObject<HTMLIFrameElement | n
|
|
|
221
221
|
|
|
222
222
|
/**
|
|
223
223
|
* True when the caption preview iframe is mounted AND visible. The caption
|
|
224
|
-
* store's isEditMode stays true while the preview is merely hidden
|
|
225
|
-
*
|
|
226
|
-
* the user can actually see the captions the undo would change.
|
|
224
|
+
* store's isEditMode stays true while the preview is merely hidden, so hotkeys must not
|
|
225
|
+
* route ⌘Z to the caption stack unless the user can see the captions the undo would change.
|
|
227
226
|
*/
|
|
228
227
|
export function isCaptionPreviewVisible(): boolean {
|
|
229
228
|
const iframe = registeredIframe?.current;
|
|
@@ -213,7 +213,7 @@ export const CaptionPropertyPanel = memo(function CaptionPropertyPanel({
|
|
|
213
213
|
return (
|
|
214
214
|
<div className="flex flex-col h-full min-h-0">
|
|
215
215
|
{/* Header */}
|
|
216
|
-
<div className="px-3 py-2 border-b border-neutral-800
|
|
216
|
+
<div className="px-3 py-2 border-b border-neutral-800 shrink-0">
|
|
217
217
|
<div className="flex items-center justify-between mb-1.5">
|
|
218
218
|
<span className="text-2xs text-neutral-500">{countLabel}</span>
|
|
219
219
|
</div>
|
|
@@ -225,7 +225,7 @@ export const CaptionPropertyPanel = memo(function CaptionPropertyPanel({
|
|
|
225
225
|
aria-selected={activeTab === "style"}
|
|
226
226
|
onClick={() => setActiveTab("style")}
|
|
227
227
|
className={[
|
|
228
|
-
"flex-1 py-0.5 rounded text-2xs font-medium transition-colors",
|
|
228
|
+
"flex-1 py-0.5 rounded-sm text-2xs font-medium transition-colors",
|
|
229
229
|
activeTab === "style"
|
|
230
230
|
? "bg-studio-accent/20 text-studio-accent border border-studio-accent/50"
|
|
231
231
|
: "text-neutral-500 border border-neutral-800 hover:text-neutral-300 hover:border-neutral-600",
|
|
@@ -239,7 +239,7 @@ export const CaptionPropertyPanel = memo(function CaptionPropertyPanel({
|
|
|
239
239
|
aria-selected={activeTab === "animation"}
|
|
240
240
|
onClick={() => setActiveTab("animation")}
|
|
241
241
|
className={[
|
|
242
|
-
"flex-1 py-0.5 rounded text-2xs font-medium transition-colors",
|
|
242
|
+
"flex-1 py-0.5 rounded-sm text-2xs font-medium transition-colors",
|
|
243
243
|
activeTab === "animation"
|
|
244
244
|
? "bg-studio-accent/20 text-studio-accent border border-studio-accent/50"
|
|
245
245
|
: "text-neutral-500 border border-neutral-800 hover:text-neutral-300 hover:border-neutral-600",
|
|
@@ -109,7 +109,7 @@ export const CaptionTimeline = memo(function CaptionTimeline({
|
|
|
109
109
|
tabIndex={0}
|
|
110
110
|
aria-label={`Caption word "${seg.text}"`}
|
|
111
111
|
aria-pressed={isSelected}
|
|
112
|
-
className={`absolute top-1 bottom-1 rounded flex items-center overflow-hidden cursor-pointer focus-visible:ring-1 focus-visible:ring-white outline-
|
|
112
|
+
className={`absolute top-1 bottom-1 rounded flex items-center overflow-hidden cursor-pointer focus-visible:ring-1 focus-visible:ring-white outline-hidden${
|
|
113
113
|
isSelected ? " ring-1 ring-white/50 z-10" : ""
|
|
114
114
|
}`}
|
|
115
115
|
style={{
|
|
@@ -2,7 +2,7 @@ import type React from "react";
|
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
|
|
4
4
|
export const inputCls =
|
|
5
|
-
"w-full bg-neutral-900 border border-neutral-800 rounded px-1.5 py-0.5 text-2xs text-neutral-200 font-mono outline-
|
|
5
|
+
"w-full bg-neutral-900 border border-neutral-800 rounded-sm px-1.5 py-0.5 text-2xs text-neutral-200 font-mono outline-hidden focus:border-studio-accent disabled:opacity-40 disabled:cursor-not-allowed";
|
|
6
6
|
|
|
7
7
|
export function Section({ label, children }: { label: string; children: React.ReactNode }) {
|
|
8
8
|
return (
|
|
@@ -20,7 +20,7 @@ export function Section({ label, children }: { label: string; children: React.Re
|
|
|
20
20
|
export function Row({ label, children }: { label: string; children: React.ReactNode }) {
|
|
21
21
|
return (
|
|
22
22
|
<div className="flex items-center gap-2">
|
|
23
|
-
<span className="text-2xs text-neutral-600 w-14 text-right
|
|
23
|
+
<span className="text-2xs text-neutral-600 w-14 text-right shrink-0">{label}</span>
|
|
24
24
|
<div className="flex-1 min-w-0">{children}</div>
|
|
25
25
|
</div>
|
|
26
26
|
);
|
|
@@ -66,8 +66,8 @@ export function AskAgentModal({
|
|
|
66
66
|
<div
|
|
67
67
|
className={
|
|
68
68
|
anchorPoint
|
|
69
|
-
? "hf-backdrop-in fixed inset-0 z-
|
|
70
|
-
: "hf-backdrop-in fixed inset-0 z-
|
|
69
|
+
? "hf-backdrop-in fixed inset-0 z-100 bg-black/60 backdrop-blur-xs"
|
|
70
|
+
: "hf-backdrop-in fixed inset-0 z-100 flex items-center justify-center bg-black/60 backdrop-blur-xs"
|
|
71
71
|
}
|
|
72
72
|
onClick={requestClose}
|
|
73
73
|
>
|
|
@@ -77,7 +77,7 @@ export function AskAgentModal({
|
|
|
77
77
|
aria-modal="true"
|
|
78
78
|
aria-label="Copy prompt to AI agent"
|
|
79
79
|
tabIndex={-1}
|
|
80
|
-
className={`w-[480px] rounded-2xl border border-neutral-800 bg-neutral-950 shadow-2xl outline-
|
|
80
|
+
className={`w-[480px] rounded-2xl border border-neutral-800 bg-neutral-950 shadow-2xl outline-hidden ${
|
|
81
81
|
anchorPoint ? "fixed" : ""
|
|
82
82
|
}`}
|
|
83
83
|
style={modalPositionStyle}
|
|
@@ -112,7 +112,7 @@ export function AskAgentModal({
|
|
|
112
112
|
<div className="px-5 py-4 space-y-3">
|
|
113
113
|
<textarea
|
|
114
114
|
ref={inputRef}
|
|
115
|
-
className="w-full h-24 px-3 py-2 rounded-lg border border-neutral-800 bg-neutral-900/60 text-sm text-neutral-200 placeholder-neutral-600 resize-none focus:outline-
|
|
115
|
+
className="w-full h-24 px-3 py-2 rounded-lg border border-neutral-800 bg-neutral-900/60 text-sm text-neutral-200 placeholder-neutral-600 resize-none focus:outline-hidden focus:border-studio-accent/60 focus:ring-1 focus:ring-studio-accent/30"
|
|
116
116
|
placeholder="Describe what you want to change…"
|
|
117
117
|
value={value}
|
|
118
118
|
onChange={(e) => setValue(e.target.value)}
|
|
@@ -127,7 +127,7 @@ export function AskAgentModal({
|
|
|
127
127
|
<summary className="text-[11px] text-neutral-500 cursor-pointer select-none hover:text-neutral-400">
|
|
128
128
|
Context included in prompt
|
|
129
129
|
</summary>
|
|
130
|
-
<pre className="mt-2 max-h-40 overflow-auto rounded-lg bg-neutral-900/80 px-3 py-2 text-[11px] leading-relaxed text-neutral-500 whitespace-pre-wrap break-
|
|
130
|
+
<pre className="mt-2 max-h-40 overflow-auto rounded-lg bg-neutral-900/80 px-3 py-2 text-[11px] leading-relaxed text-neutral-500 whitespace-pre-wrap wrap-break-word border border-neutral-800/50">
|
|
131
131
|
{contextPreview}
|
|
132
132
|
</pre>
|
|
133
133
|
</details>
|
|
@@ -42,7 +42,6 @@ vi.mock("./nle/NLEContext", () => ({
|
|
|
42
42
|
useNLEContext: () => ({
|
|
43
43
|
compositionStack: [],
|
|
44
44
|
updateCompositionStack: vi.fn(),
|
|
45
|
-
containerRef: { current: null },
|
|
46
45
|
}),
|
|
47
46
|
}));
|
|
48
47
|
vi.mock("./nle/useTimelineEditCallbacks", () => ({
|
|
@@ -53,7 +52,14 @@ vi.mock("./nle/PreviewOverlays", () => ({ PreviewOverlays: () => null }));
|
|
|
53
52
|
vi.mock("./nle/TimelinePane", () => ({ TimelinePane: () => null }));
|
|
54
53
|
vi.mock("../captions/components/CaptionTimeline", () => ({ CaptionTimeline: () => null }));
|
|
55
54
|
|
|
56
|
-
Object.assign(globalThis, {
|
|
55
|
+
Object.assign(globalThis, {
|
|
56
|
+
IS_REACT_ACT_ENVIRONMENT: true,
|
|
57
|
+
ResizeObserver: class {
|
|
58
|
+
observe() {}
|
|
59
|
+
unobserve() {}
|
|
60
|
+
disconnect() {}
|
|
61
|
+
},
|
|
62
|
+
});
|
|
57
63
|
|
|
58
64
|
afterEach(() => {
|
|
59
65
|
document.body.innerHTML = "";
|
|
@@ -69,8 +75,7 @@ describe("EditorShell timeline selection sync", () => {
|
|
|
69
75
|
act(() => {
|
|
70
76
|
root.render(
|
|
71
77
|
<EditorShell
|
|
72
|
-
|
|
73
|
-
right={null}
|
|
78
|
+
panels={null}
|
|
74
79
|
timelineToolbar={null}
|
|
75
80
|
renderClipContent={() => null}
|
|
76
81
|
handleTimelineElementDelete={vi.fn()}
|
|
@@ -16,22 +16,19 @@ import type { BlockPreviewInfo } from "./sidebar/BlocksTab";
|
|
|
16
16
|
import type { GestureRecordingState } from "./editor/GestureRecordControl";
|
|
17
17
|
import { useTimelineSelectionPreviewSync } from "../hooks/useTimelineSelectionPreviewSync";
|
|
18
18
|
import { StudioAgentTools } from "../webmcp/StudioAgentTools";
|
|
19
|
+
import type { TimelineDropPlacement } from "../player/components/timelineCallbacks";
|
|
20
|
+
import { Dock } from "./dock/Dock";
|
|
19
21
|
|
|
20
22
|
type RenderClipContent = (
|
|
21
23
|
element: TimelineElement,
|
|
22
24
|
style: { clip: string; label: string },
|
|
23
25
|
) => ReactNode;
|
|
24
|
-
type TimelineDropPlacement = Pick<TimelineElement, "start" | "track">;
|
|
25
26
|
|
|
26
27
|
// The seven move/resize/split/razor handlers come from TimelineEditCallbackDeps
|
|
27
28
|
// (shared with useTimelineEditCallbacks); the rest are drop + wiring props.
|
|
28
29
|
export interface EditorShellProps extends TimelineEditCallbackDeps {
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
/** Right panel (inspector/design) or null when collapsed, in the top row. */
|
|
32
|
-
right: ReactNode;
|
|
33
|
-
/** Hide the whole shell (e.g. while the storyboard view is active). */
|
|
34
|
-
hidden?: boolean;
|
|
30
|
+
/** Dock.Panel elements for every panel except the built-in preview and timeline. */
|
|
31
|
+
panels: ReactNode;
|
|
35
32
|
timelineToolbar: ReactNode;
|
|
36
33
|
renderClipContent: RenderClipContent;
|
|
37
34
|
handleTimelineElementDelete: (element: TimelineElement) => Promise<void> | void;
|
|
@@ -67,16 +64,18 @@ export interface EditorShellProps extends TimelineEditCallbackDeps {
|
|
|
67
64
|
isGestureRecording?: boolean;
|
|
68
65
|
recordingState?: GestureRecordingState;
|
|
69
66
|
onToggleRecording?: () => void;
|
|
67
|
+
/**
|
|
68
|
+
* Host layer over the preview, positioned with `usePreviewCompositionRect`. Hidden in
|
|
69
|
+
* fullscreen and during a block preview; below the selection overlay past z-index 10.
|
|
70
|
+
*/
|
|
70
71
|
gestureOverlay?: ReactNode;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
// The
|
|
74
|
-
//
|
|
75
|
-
//
|
|
74
|
+
// The dockable shell: every panel lives in one Dock, arranged by the user's
|
|
75
|
+
// saved layout. Owns the shared player + composition-stack state via
|
|
76
|
+
// NLEProvider so every panel shares one player.
|
|
76
77
|
export function EditorShell({
|
|
77
|
-
|
|
78
|
-
right,
|
|
79
|
-
hidden,
|
|
78
|
+
panels,
|
|
80
79
|
timelineToolbar,
|
|
81
80
|
renderClipContent,
|
|
82
81
|
handleTimelineElementDelete,
|
|
@@ -157,7 +156,7 @@ export function EditorShell({
|
|
|
157
156
|
});
|
|
158
157
|
|
|
159
158
|
return (
|
|
160
|
-
<div className=
|
|
159
|
+
<div className="flex flex-col flex-1 min-h-0">
|
|
161
160
|
<TimelineEditProvider value={timelineEditCallbacks}>
|
|
162
161
|
<NLEProvider
|
|
163
162
|
projectId={projectId}
|
|
@@ -177,8 +176,8 @@ export function EditorShell({
|
|
|
177
176
|
}}
|
|
178
177
|
>
|
|
179
178
|
<EditorShellBody
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
projectId={projectId}
|
|
180
|
+
panels={panels}
|
|
182
181
|
captionEditMode={captionEditMode}
|
|
183
182
|
onSelectTimelineElement={handleTimelineElementSelect}
|
|
184
183
|
onPreviewBlockDrop={handlePreviewBlockDrop}
|
|
@@ -212,8 +211,8 @@ export function EditorShell({
|
|
|
212
211
|
}
|
|
213
212
|
|
|
214
213
|
interface EditorShellBodyProps {
|
|
215
|
-
|
|
216
|
-
|
|
214
|
+
panels: ReactNode;
|
|
215
|
+
projectId: string;
|
|
217
216
|
captionEditMode: boolean;
|
|
218
217
|
previewOverlay: ReactNode;
|
|
219
218
|
onSelectTimelineElement: (element: TimelineElement | null) => void;
|
|
@@ -238,8 +237,8 @@ interface EditorShellBodyProps {
|
|
|
238
237
|
}
|
|
239
238
|
|
|
240
239
|
function EditorShellBody({
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
panels,
|
|
241
|
+
projectId,
|
|
243
242
|
captionEditMode,
|
|
244
243
|
previewOverlay,
|
|
245
244
|
onSelectTimelineElement,
|
|
@@ -256,7 +255,7 @@ function EditorShellBody({
|
|
|
256
255
|
onDuplicateClip,
|
|
257
256
|
canPasteClip,
|
|
258
257
|
}: EditorShellBodyProps) {
|
|
259
|
-
const { compositionStack, updateCompositionStack
|
|
258
|
+
const { compositionStack, updateCompositionStack } = useNLEContext();
|
|
260
259
|
|
|
261
260
|
// The caption track's blocks are seek targets; CaptionTimeline took an onSeek
|
|
262
261
|
// prop that nothing ever passed, so clicking a block did nothing.
|
|
@@ -276,57 +275,55 @@ function EditorShellBody({
|
|
|
276
275
|
|
|
277
276
|
return (
|
|
278
277
|
<div
|
|
279
|
-
ref={containerRef}
|
|
280
278
|
// Shell canvas is a step LIGHTER than the near-black panel cards so the
|
|
281
279
|
// gaps between panels read as visible seams (CapCut-style).
|
|
282
|
-
className="flex flex-col flex-1 min-h-0 bg-
|
|
280
|
+
className="flex flex-col flex-1 min-h-0 bg-panel-surface"
|
|
283
281
|
onKeyDown={handleKeyDown}
|
|
284
282
|
tabIndex={-1}
|
|
285
283
|
>
|
|
286
284
|
{/* Renders nothing; exposes Studio's state to an agentic browser. Mounted
|
|
287
285
|
here rather than in App because it needs the DomEdit contexts. */}
|
|
288
286
|
<StudioAgentTools />
|
|
289
|
-
{
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
287
|
+
<Dock.Root projectId={projectId}>
|
|
288
|
+
<Dock.Panel id="preview">
|
|
289
|
+
<div className="relative flex h-full w-full min-w-0 flex-col">
|
|
290
|
+
<PreviewPane
|
|
291
|
+
previewOverlay={previewOverlay}
|
|
292
|
+
onSelectTimelineElement={onSelectTimelineElement}
|
|
293
|
+
onPreviewBlockDrop={onPreviewBlockDrop}
|
|
294
|
+
/>
|
|
295
|
+
</div>
|
|
296
|
+
</Dock.Panel>
|
|
297
|
+
<Dock.Panel id="timeline">
|
|
298
|
+
<TimelinePane
|
|
299
|
+
timelineToolbar={timelineToolbar}
|
|
300
|
+
renderClipContent={renderClipContent}
|
|
301
|
+
onFileDrop={onFileDrop}
|
|
302
|
+
onAssetDrop={onAssetDrop}
|
|
303
|
+
onBlockDrop={onBlockDrop}
|
|
304
|
+
onCompositionDrop={onCompositionDrop}
|
|
305
|
+
onDeleteElement={onDeleteElement}
|
|
306
|
+
onCopyClip={onCopyClip}
|
|
307
|
+
onPasteClip={onPasteClip}
|
|
308
|
+
onDuplicateClip={onDuplicateClip}
|
|
309
|
+
canPasteClip={canPasteClip}
|
|
296
310
|
onSelectTimelineElement={onSelectTimelineElement}
|
|
297
|
-
|
|
311
|
+
timelineFooter={
|
|
312
|
+
captionEditMode ? (
|
|
313
|
+
<div className="border-t border-neutral-800/30 shrink-0" style={{ height: 60 }}>
|
|
314
|
+
<div className="flex items-center gap-1.5 px-2 py-0.5">
|
|
315
|
+
<span className="text-[9px] font-medium text-neutral-500 uppercase tracking-wider">
|
|
316
|
+
Captions
|
|
317
|
+
</span>
|
|
318
|
+
</div>
|
|
319
|
+
<CaptionTimeline pixelsPerSecond={100} onSeek={seekCaptionTime} />
|
|
320
|
+
</div>
|
|
321
|
+
) : undefined
|
|
322
|
+
}
|
|
298
323
|
/>
|
|
299
|
-
</
|
|
300
|
-
{
|
|
301
|
-
</
|
|
302
|
-
|
|
303
|
-
{/* Full-width timeline row */}
|
|
304
|
-
<TimelinePane
|
|
305
|
-
timelineToolbar={timelineToolbar}
|
|
306
|
-
renderClipContent={renderClipContent}
|
|
307
|
-
onFileDrop={onFileDrop}
|
|
308
|
-
onAssetDrop={onAssetDrop}
|
|
309
|
-
onBlockDrop={onBlockDrop}
|
|
310
|
-
onCompositionDrop={onCompositionDrop}
|
|
311
|
-
onDeleteElement={onDeleteElement}
|
|
312
|
-
onCopyClip={onCopyClip}
|
|
313
|
-
onPasteClip={onPasteClip}
|
|
314
|
-
onDuplicateClip={onDuplicateClip}
|
|
315
|
-
canPasteClip={canPasteClip}
|
|
316
|
-
onSelectTimelineElement={onSelectTimelineElement}
|
|
317
|
-
timelineFooter={
|
|
318
|
-
captionEditMode ? (
|
|
319
|
-
<div className="border-t border-neutral-800/30 flex-shrink-0" style={{ height: 60 }}>
|
|
320
|
-
<div className="flex items-center gap-1.5 px-2 py-0.5">
|
|
321
|
-
<span className="text-[9px] font-medium text-neutral-500 uppercase tracking-wider">
|
|
322
|
-
Captions
|
|
323
|
-
</span>
|
|
324
|
-
</div>
|
|
325
|
-
<CaptionTimeline pixelsPerSecond={100} onSeek={seekCaptionTime} />
|
|
326
|
-
</div>
|
|
327
|
-
) : undefined
|
|
328
|
-
}
|
|
329
|
-
/>
|
|
324
|
+
</Dock.Panel>
|
|
325
|
+
{panels}
|
|
326
|
+
</Dock.Root>
|
|
330
327
|
</div>
|
|
331
328
|
);
|
|
332
329
|
}
|
|
@@ -32,7 +32,7 @@ function ConflictReview({
|
|
|
32
32
|
|
|
33
33
|
return (
|
|
34
34
|
<div
|
|
35
|
-
className="fixed inset-0 z-
|
|
35
|
+
className="fixed inset-0 z-110 flex items-center justify-center bg-black/70 px-5 backdrop-blur-xs"
|
|
36
36
|
onClick={onClose}
|
|
37
37
|
>
|
|
38
38
|
<div
|
|
@@ -41,7 +41,7 @@ function ConflictReview({
|
|
|
41
41
|
aria-modal="true"
|
|
42
42
|
aria-labelledby="external-conflict-title"
|
|
43
43
|
tabIndex={-1}
|
|
44
|
-
className="max-h-[88vh] w-full max-w-5xl overflow-auto rounded-xl border border-amber-400/30 bg-neutral-950 p-5 text-neutral-100 shadow-2xl outline-
|
|
44
|
+
className="max-h-[88vh] w-full max-w-5xl overflow-auto rounded-xl border border-amber-400/30 bg-neutral-950 p-5 text-neutral-100 shadow-2xl outline-hidden"
|
|
45
45
|
onClick={(event) => event.stopPropagation()}
|
|
46
46
|
>
|
|
47
47
|
<div className="flex items-start justify-between gap-4">
|
|
@@ -53,7 +53,7 @@ function ConflictReview({
|
|
|
53
53
|
Reviewing or exporting does not change either version.
|
|
54
54
|
</p>
|
|
55
55
|
</div>
|
|
56
|
-
<button type="button" onClick={onClose} className="rounded px-2 py-1 text-neutral-400">
|
|
56
|
+
<button type="button" onClick={onClose} className="rounded-sm px-2 py-1 text-neutral-400">
|
|
57
57
|
Close
|
|
58
58
|
</button>
|
|
59
59
|
</div>
|
|
@@ -68,14 +68,14 @@ function ConflictReview({
|
|
|
68
68
|
<div className="flex gap-2">
|
|
69
69
|
<button
|
|
70
70
|
type="button"
|
|
71
|
-
className="rounded border border-neutral-700 px-2 py-1 text-[11px]"
|
|
71
|
+
className="rounded-sm border border-neutral-700 px-2 py-1 text-[11px]"
|
|
72
72
|
onClick={() => void navigator.clipboard.writeText(side.content)}
|
|
73
73
|
>
|
|
74
74
|
Copy
|
|
75
75
|
</button>
|
|
76
76
|
<button
|
|
77
77
|
type="button"
|
|
78
|
-
className="rounded border border-neutral-700 px-2 py-1 text-[11px]"
|
|
78
|
+
className="rounded-sm border border-neutral-700 px-2 py-1 text-[11px]"
|
|
79
79
|
onClick={() =>
|
|
80
80
|
downloadText(`${conflict.error.filePath}.${side.suffix}.html`, side.content)
|
|
81
81
|
}
|
|
@@ -87,7 +87,7 @@ function ConflictReview({
|
|
|
87
87
|
<textarea
|
|
88
88
|
readOnly
|
|
89
89
|
value={side.content}
|
|
90
|
-
className="h-80 w-full resize-y rounded border border-neutral-800 bg-neutral-900 p-3 font-mono text-[11px] leading-relaxed text-neutral-300"
|
|
90
|
+
className="h-80 w-full resize-y rounded-sm border border-neutral-800 bg-neutral-900 p-3 font-mono text-[11px] leading-relaxed text-neutral-300"
|
|
91
91
|
/>
|
|
92
92
|
</section>
|
|
93
93
|
))}
|
|
@@ -110,7 +110,7 @@ function FailedDraftReview({
|
|
|
110
110
|
useDialogBehavior({ open: true, onClose, containerRef });
|
|
111
111
|
return (
|
|
112
112
|
<div
|
|
113
|
-
className="fixed inset-0 z-
|
|
113
|
+
className="fixed inset-0 z-110 flex items-center justify-center bg-black/70 px-5 backdrop-blur-xs"
|
|
114
114
|
onClick={onClose}
|
|
115
115
|
>
|
|
116
116
|
<div
|
|
@@ -119,7 +119,7 @@ function FailedDraftReview({
|
|
|
119
119
|
aria-modal="true"
|
|
120
120
|
aria-labelledby="failed-draft-title"
|
|
121
121
|
tabIndex={-1}
|
|
122
|
-
className="max-h-[88vh] w-full max-w-3xl overflow-auto rounded-xl border border-amber-400/30 bg-neutral-950 p-5 text-neutral-100 shadow-2xl outline-
|
|
122
|
+
className="max-h-[88vh] w-full max-w-3xl overflow-auto rounded-xl border border-amber-400/30 bg-neutral-950 p-5 text-neutral-100 shadow-2xl outline-hidden"
|
|
123
123
|
onClick={(event) => event.stopPropagation()}
|
|
124
124
|
>
|
|
125
125
|
<div className="flex items-start justify-between gap-4">
|
|
@@ -131,21 +131,21 @@ function FailedDraftReview({
|
|
|
131
131
|
Copy or download this draft before choosing to discard it.
|
|
132
132
|
</p>
|
|
133
133
|
</div>
|
|
134
|
-
<button type="button" onClick={onClose} className="rounded px-2 py-1 text-neutral-400">
|
|
134
|
+
<button type="button" onClick={onClose} className="rounded-sm px-2 py-1 text-neutral-400">
|
|
135
135
|
Close
|
|
136
136
|
</button>
|
|
137
137
|
</div>
|
|
138
138
|
<div className="mt-4 flex justify-end gap-2">
|
|
139
139
|
<button
|
|
140
140
|
type="button"
|
|
141
|
-
className="rounded border border-neutral-700 px-2 py-1 text-[11px]"
|
|
141
|
+
className="rounded-sm border border-neutral-700 px-2 py-1 text-[11px]"
|
|
142
142
|
onClick={() => void navigator.clipboard.writeText(content)}
|
|
143
143
|
>
|
|
144
144
|
Copy
|
|
145
145
|
</button>
|
|
146
146
|
<button
|
|
147
147
|
type="button"
|
|
148
|
-
className="rounded border border-neutral-700 px-2 py-1 text-[11px]"
|
|
148
|
+
className="rounded-sm border border-neutral-700 px-2 py-1 text-[11px]"
|
|
149
149
|
onClick={() => downloadText(`${path}.studio.html`, content)}
|
|
150
150
|
>
|
|
151
151
|
Download
|
|
@@ -154,7 +154,7 @@ function FailedDraftReview({
|
|
|
154
154
|
<textarea
|
|
155
155
|
readOnly
|
|
156
156
|
value={content}
|
|
157
|
-
className="mt-2 h-80 w-full resize-y rounded border border-neutral-800 bg-neutral-900 p-3 font-mono text-[11px] leading-relaxed text-neutral-300"
|
|
157
|
+
className="mt-2 h-80 w-full resize-y rounded-sm border border-neutral-800 bg-neutral-900 p-3 font-mono text-[11px] leading-relaxed text-neutral-300"
|
|
158
158
|
/>
|
|
159
159
|
</div>
|
|
160
160
|
</div>
|
|
@@ -176,7 +176,7 @@ export function ExternalFileConflictBanner({
|
|
|
176
176
|
<>
|
|
177
177
|
<div
|
|
178
178
|
role="alert"
|
|
179
|
-
className="absolute left-1/2 top-14 z-
|
|
179
|
+
className="absolute left-1/2 top-14 z-94 flex max-w-[calc(100vw-32px)] -translate-x-1/2 flex-wrap items-center gap-3 rounded-md border border-amber-400/30 bg-amber-950/95 px-4 py-2 text-[12px] font-medium text-amber-50 shadow-lg"
|
|
180
180
|
>
|
|
181
181
|
<span>
|
|
182
182
|
{conflict
|
|
@@ -201,7 +201,7 @@ export function ExternalFileConflictBanner({
|
|
|
201
201
|
<button
|
|
202
202
|
type="button"
|
|
203
203
|
onClick={() => void coordinator.useExternalFile()}
|
|
204
|
-
className="rounded border border-amber-200/30 px-2 py-1"
|
|
204
|
+
className="rounded-sm border border-amber-200/30 px-2 py-1"
|
|
205
205
|
>
|
|
206
206
|
Discard Studio edits and reload file
|
|
207
207
|
</button>
|
|
@@ -217,7 +217,7 @@ export function ExternalFileConflictBanner({
|
|
|
217
217
|
void coordinator.keepStudioFile();
|
|
218
218
|
}
|
|
219
219
|
}}
|
|
220
|
-
className="rounded border border-red-300/40 px-2 py-1 text-red-100"
|
|
220
|
+
className="rounded-sm border border-red-300/40 px-2 py-1 text-red-100"
|
|
221
221
|
>
|
|
222
222
|
Overwrite file with Studio version
|
|
223
223
|
</button>
|
|
@@ -234,7 +234,7 @@ export function ExternalFileConflictBanner({
|
|
|
234
234
|
void coordinator.keepStudioFile();
|
|
235
235
|
}
|
|
236
236
|
}}
|
|
237
|
-
className="rounded border border-red-300/40 px-2 py-1 text-red-100"
|
|
237
|
+
className="rounded-sm border border-red-300/40 px-2 py-1 text-red-100"
|
|
238
238
|
>
|
|
239
239
|
Overwrite file with recovered Studio draft
|
|
240
240
|
</button>
|
|
@@ -58,7 +58,7 @@ export function LintModal({
|
|
|
58
58
|
|
|
59
59
|
return (
|
|
60
60
|
<div
|
|
61
|
-
className="hf-backdrop-in fixed inset-0 z-
|
|
61
|
+
className="hf-backdrop-in fixed inset-0 z-100 flex items-center justify-center bg-black/60 backdrop-blur-xs"
|
|
62
62
|
onClick={requestClose}
|
|
63
63
|
>
|
|
64
64
|
<div
|
|
@@ -67,7 +67,7 @@ export function LintModal({
|
|
|
67
67
|
aria-modal="true"
|
|
68
68
|
aria-label={title}
|
|
69
69
|
tabIndex={-1}
|
|
70
|
-
className="bg-neutral-950 border border-neutral-800 rounded-xl shadow-2xl w-full max-w-xl max-h-[80vh] flex flex-col overflow-hidden outline-
|
|
70
|
+
className="bg-neutral-950 border border-neutral-800 rounded-xl shadow-2xl w-full max-w-xl max-h-[80vh] flex flex-col overflow-hidden outline-hidden"
|
|
71
71
|
onClick={(e) => e.stopPropagation()}
|
|
72
72
|
>
|
|
73
73
|
{/* Header */}
|
|
@@ -130,20 +130,13 @@ export function LintModal({
|
|
|
130
130
|
{errors.map((f, i) => (
|
|
131
131
|
<div key={`e-${i}`} className="py-3 border-b border-neutral-800/50 last:border-0">
|
|
132
132
|
<div className="flex items-start gap-2">
|
|
133
|
-
<WarningIcon
|
|
134
|
-
size={14}
|
|
135
|
-
className="text-red-400 flex-shrink-0 mt-0.5"
|
|
136
|
-
weight="fill"
|
|
137
|
-
/>
|
|
133
|
+
<WarningIcon size={14} className="text-red-400 shrink-0 mt-0.5" weight="fill" />
|
|
138
134
|
<div className="min-w-0">
|
|
139
135
|
<p className="text-sm text-neutral-200">{f.message}</p>
|
|
140
136
|
{f.file && <p className="text-xs text-neutral-600 font-mono mt-0.5">{f.file}</p>}
|
|
141
137
|
{f.fixHint && (
|
|
142
138
|
<div className="flex items-start gap-1 mt-1.5">
|
|
143
|
-
<CaretRightIcon
|
|
144
|
-
size={10}
|
|
145
|
-
className="text-studio-accent flex-shrink-0 mt-0.5"
|
|
146
|
-
/>
|
|
139
|
+
<CaretRightIcon size={10} className="text-studio-accent shrink-0 mt-0.5" />
|
|
147
140
|
<p className="text-xs text-studio-accent">{f.fixHint}</p>
|
|
148
141
|
</div>
|
|
149
142
|
)}
|
|
@@ -154,16 +147,13 @@ export function LintModal({
|
|
|
154
147
|
{warnings.map((f, i) => (
|
|
155
148
|
<div key={`w-${i}`} className="py-3 border-b border-neutral-800/50 last:border-0">
|
|
156
149
|
<div className="flex items-start gap-2">
|
|
157
|
-
<WarningIcon size={14} className="text-amber-400
|
|
150
|
+
<WarningIcon size={14} className="text-amber-400 shrink-0 mt-0.5" />
|
|
158
151
|
<div className="min-w-0">
|
|
159
152
|
<p className="text-sm text-neutral-300">{f.message}</p>
|
|
160
153
|
{f.file && <p className="text-xs text-neutral-600 font-mono mt-0.5">{f.file}</p>}
|
|
161
154
|
{f.fixHint && (
|
|
162
155
|
<div className="flex items-start gap-1 mt-1.5">
|
|
163
|
-
<CaretRightIcon
|
|
164
|
-
size={10}
|
|
165
|
-
className="text-studio-accent flex-shrink-0 mt-0.5"
|
|
166
|
-
/>
|
|
156
|
+
<CaretRightIcon size={10} className="text-studio-accent shrink-0 mt-0.5" />
|
|
167
157
|
<p className="text-xs text-studio-accent">{f.fixHint}</p>
|
|
168
158
|
</div>
|
|
169
159
|
)}
|
|
@@ -45,7 +45,7 @@ export function MediaPreview({ projectId, filePath }: { projectId: string; fileP
|
|
|
45
45
|
src={serveUrl}
|
|
46
46
|
alt={name}
|
|
47
47
|
onError={setFailed}
|
|
48
|
-
className="max-w-full max-h-[70%] object-contain rounded border border-neutral-800"
|
|
48
|
+
className="max-w-full max-h-[70%] object-contain rounded-sm border border-neutral-800"
|
|
49
49
|
/>
|
|
50
50
|
<span className="mt-3 text-[11px] text-neutral-500 font-mono">{filePath}</span>
|
|
51
51
|
</div>
|
|
@@ -59,7 +59,7 @@ export function MediaPreview({ projectId, filePath }: { projectId: string; fileP
|
|
|
59
59
|
src={serveUrl}
|
|
60
60
|
controls
|
|
61
61
|
onError={setFailed}
|
|
62
|
-
className="max-w-full max-h-[70%] rounded border border-neutral-800"
|
|
62
|
+
className="max-w-full max-h-[70%] rounded-sm border border-neutral-800"
|
|
63
63
|
/>
|
|
64
64
|
<span className="mt-3 text-[11px] text-neutral-500 font-mono">{filePath}</span>
|
|
65
65
|
</div>
|