forked from 77media/video-flow
剧本修改以及加暂停/继续按钮
This commit is contained in:
parent
e983a10037
commit
508065107a
@ -613,7 +613,7 @@ export function CreateToVideo2() {
|
|||||||
{script}
|
{script}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`custom-placeholder absolute top-[50%] left-[10px] z-10 translate-y-[-50%] flex items-center gap-1 pointer-events-none text-[14px] leading-[26px] text-white/[0.40] ${script ? 'opacity-0' : 'opacity-100'}`}
|
className={`custom-placeholder absolute top-[50%] left-[10px] z-10 translate-y-[-50%] flex items-center gap-1 pointer-events-none text-[14px] leading-[26px] text-white/[0.40] ${script ? 'hidden' : 'block'}`}
|
||||||
>
|
>
|
||||||
<span>Describe the content you want to action. Get an </span>
|
<span>Describe the content you want to action. Get an </span>
|
||||||
<b
|
<b
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
.container-H2sRZG {
|
.container-H2sRZG {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-inline: 24px;
|
/* padding-inline: 24px; */
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -15,14 +15,14 @@
|
|||||||
/* 小屏幕适配 */
|
/* 小屏幕适配 */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.container-H2sRZG {
|
.container-H2sRZG {
|
||||||
padding-inline: 12px;
|
padding-inline: 10px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: calc(100vh - 80px);
|
height: calc(100vh - 80px);
|
||||||
min-height: 500px;
|
min-height: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.splashContainer-otuV_A {
|
.splashContainer-otuV_A {
|
||||||
gap: 12px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-Ocdu1O {
|
.media-Ocdu1O {
|
||||||
@ -52,7 +52,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.info-UUGkPJ {
|
.info-UUGkPJ {
|
||||||
gap: 8px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.splashContainer-otuV_A {
|
.splashContainer-otuV_A {
|
||||||
gap: 8px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videoContainer-qteKNi {
|
.videoContainer-qteKNi {
|
||||||
@ -88,14 +88,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.info-UUGkPJ {
|
.info-UUGkPJ {
|
||||||
gap: 6px;
|
gap: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 默认小屏幕布局 */
|
/* 默认小屏幕布局 */
|
||||||
.splashContainer-otuV_A {
|
.splashContainer-otuV_A {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 16px;
|
gap: 8px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@ -106,7 +106,7 @@
|
|||||||
.splashContainer-otuV_A {
|
.splashContainer-otuV_A {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
grid-template-rows: auto 1fr;
|
grid-template-rows: auto 1fr;
|
||||||
gap: 24px;
|
gap: 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@
|
|||||||
.info-UUGkPJ {
|
.info-UUGkPJ {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,8 +10,9 @@ import { MediaViewer } from "./work-flow/media-viewer";
|
|||||||
import { ThumbnailGrid } from "./work-flow/thumbnail-grid";
|
import { ThumbnailGrid } from "./work-flow/thumbnail-grid";
|
||||||
import { useWorkflowData } from "./work-flow/use-workflow-data";
|
import { useWorkflowData } from "./work-flow/use-workflow-data";
|
||||||
import { usePlaybackControls } from "./work-flow/use-playback-controls";
|
import { usePlaybackControls } from "./work-flow/use-playback-controls";
|
||||||
import { AlertCircle, RefreshCw } from "lucide-react";
|
import { AlertCircle, RefreshCw, Pause, Play } from "lucide-react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
import { GlassIconButton } from '@/components/ui/glass-icon-button';
|
||||||
|
|
||||||
export default function WorkFlow() {
|
export default function WorkFlow() {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
@ -39,6 +40,8 @@ export default function WorkFlow() {
|
|||||||
dataLoadError,
|
dataLoadError,
|
||||||
setCurrentSketchIndex,
|
setCurrentSketchIndex,
|
||||||
retryLoadData,
|
retryLoadData,
|
||||||
|
isPauseWorkFlow,
|
||||||
|
setIsPauseWorkFlow,
|
||||||
} = useWorkflowData();
|
} = useWorkflowData();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -108,7 +111,7 @@ export default function WorkFlow() {
|
|||||||
return (
|
return (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<div className="w-full overflow-hidden h-[calc(100vh-6rem)] absolute top-[4rem] left-0 right-0 px-[1rem]">
|
<div className="w-full overflow-hidden h-[calc(100vh-6rem)] absolute top-[4rem] left-0 right-0 px-[1rem]">
|
||||||
<div className="flex h-full flex-col p-6 justify-center items-center pt-0">
|
<div className="flex h-full flex-col justify-start items-center">
|
||||||
<div className="container-H2sRZG">
|
<div className="container-H2sRZG">
|
||||||
<div className="splashContainer-otuV_A">
|
<div className="splashContainer-otuV_A">
|
||||||
<div className="content-vPGYx8">
|
<div className="content-vPGYx8">
|
||||||
@ -124,10 +127,10 @@ export default function WorkFlow() {
|
|||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="media-Ocdu1O">
|
<div className="media-Ocdu1O rounded-lg">
|
||||||
<div
|
<div
|
||||||
className="videoContainer-qteKNi"
|
className="videoContainer-qteKNi"
|
||||||
style={currentStep !== '6' ? { flex: 3 } : {}}
|
style={(currentStep !== '6' && currentStep !== '0') ? { flex: 3 } : {}}
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
>
|
>
|
||||||
{dataLoadError ? (
|
{dataLoadError ? (
|
||||||
@ -208,6 +211,16 @@ export default function WorkFlow() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 暂停/播放按钮 */}
|
||||||
|
<div className="absolute right-12 bottom-12 z-[9999]">
|
||||||
|
<GlassIconButton
|
||||||
|
icon={isPauseWorkFlow ? Play : Pause}
|
||||||
|
size='lg'
|
||||||
|
tooltip={isPauseWorkFlow ? "Play" : "Pause"}
|
||||||
|
onClick={() => setIsPauseWorkFlow(!isPauseWorkFlow)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* AI 建议栏 */}
|
{/* AI 建议栏 */}
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<AISuggestionBar
|
<AISuggestionBar
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import { motion, AnimatePresence } from 'framer-motion';
|
|||||||
import { Edit3, Play, Pause, Volume2, VolumeX, Maximize, Minimize } from 'lucide-react';
|
import { Edit3, Play, Pause, Volume2, VolumeX, Maximize, Minimize } from 'lucide-react';
|
||||||
import { ProgressiveReveal, presets } from '@/components/ui/progressive-reveal';
|
import { ProgressiveReveal, presets } from '@/components/ui/progressive-reveal';
|
||||||
import { GlassIconButton } from '@/components/ui/glass-icon-button';
|
import { GlassIconButton } from '@/components/ui/glass-icon-button';
|
||||||
|
import { ScriptRenderer } from '@/components/script-renderer/ScriptRenderer';
|
||||||
|
import { mockScriptData } from '@/components/script-renderer/mock';
|
||||||
|
|
||||||
interface MediaViewerProps {
|
interface MediaViewerProps {
|
||||||
currentStep: string;
|
currentStep: string;
|
||||||
@ -795,6 +797,15 @@ export function MediaViewer({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 渲染剧本
|
||||||
|
const renderScriptContent = () => {
|
||||||
|
return (
|
||||||
|
<div className="relative w-full h-full bg-white/10 rounded-lg overflow-hidden p-2">
|
||||||
|
<ScriptRenderer data={mockScriptData} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// 根据当前步骤渲染对应内容
|
// 根据当前步骤渲染对应内容
|
||||||
if (Number(currentStep) === 6 || Number(currentStep) === 5.5) {
|
if (Number(currentStep) === 6 || Number(currentStep) === 5.5) {
|
||||||
return renderFinalVideo(currentStep);
|
return renderFinalVideo(currentStep);
|
||||||
@ -804,5 +815,9 @@ export function MediaViewer({
|
|||||||
return renderVideoContent();
|
return renderVideoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Number(currentStep) === 0) {
|
||||||
|
return renderScriptContent();
|
||||||
|
}
|
||||||
|
|
||||||
return renderSketchContent();
|
return renderSketchContent();
|
||||||
}
|
}
|
||||||
@ -73,6 +73,7 @@ export function useWorkflowData() {
|
|||||||
const [final, setFinal] = useState<any>(null);
|
const [final, setFinal] = useState<any>(null);
|
||||||
const [dataLoadError, setDataLoadError] = useState<string | null>(null);
|
const [dataLoadError, setDataLoadError] = useState<string | null>(null);
|
||||||
const [needStreamData, setNeedStreamData] = useState(false);
|
const [needStreamData, setNeedStreamData] = useState(false);
|
||||||
|
const [isPauseWorkFlow, setIsPauseWorkFlow] = useState(false);
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { sketchCount, videoCount } = useAppSelector((state) => state.workflow);
|
const { sketchCount, videoCount } = useAppSelector((state) => state.workflow);
|
||||||
@ -154,7 +155,7 @@ export function useWorkflowData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let loadingText: any = LOADING_TEXT_MAP.initializing;
|
let loadingText: any = LOADING_TEXT_MAP.initializing;
|
||||||
let finalStep = '1', sketchCount = 0, isChange = false;
|
let finalStep = '0', sketchCount = 0, isChange = false;
|
||||||
const all_task_data = response.data;
|
const all_task_data = response.data;
|
||||||
// all_task_data 下标0 和 下标1 换位置
|
// all_task_data 下标0 和 下标1 换位置
|
||||||
const temp = all_task_data[0];
|
const temp = all_task_data[0];
|
||||||
@ -166,6 +167,7 @@ export function useWorkflowData() {
|
|||||||
|
|
||||||
// 如果有已完成的数据,同步到状态
|
// 如果有已完成的数据,同步到状态
|
||||||
if (task.task_name === 'generate_sketch' && task.task_result) {
|
if (task.task_name === 'generate_sketch' && task.task_result) {
|
||||||
|
finalStep = '1';
|
||||||
const realSketchResultData = task.task_result.data.filter((item: any) => item.image_path);
|
const realSketchResultData = task.task_result.data.filter((item: any) => item.image_path);
|
||||||
if (realSketchResultData.length >= 0) {
|
if (realSketchResultData.length >= 0) {
|
||||||
// 正在生成草图中 替换 sketch 数据
|
// 正在生成草图中 替换 sketch 数据
|
||||||
@ -383,9 +385,10 @@ export function useWorkflowData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果有已完成的数据,同步到状态
|
// 如果有已完成的数据,同步到状态
|
||||||
let finalStep = '1';
|
let finalStep = '0';
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data.sketch && data.sketch.data) {
|
if (data.sketch && data.sketch.data) {
|
||||||
|
finalStep = '1';
|
||||||
const realSketchResultData = data.sketch.data.filter((item: any) => item.image_path);
|
const realSketchResultData = data.sketch.data.filter((item: any) => item.image_path);
|
||||||
const sketchList = [];
|
const sketchList = [];
|
||||||
for (const sketch of realSketchResultData) {
|
for (const sketch of realSketchResultData) {
|
||||||
@ -570,5 +573,7 @@ export function useWorkflowData() {
|
|||||||
setCurrentSketchIndex,
|
setCurrentSketchIndex,
|
||||||
retryLoadData,
|
retryLoadData,
|
||||||
handleManualPlay,
|
handleManualPlay,
|
||||||
|
isPauseWorkFlow,
|
||||||
|
setIsPauseWorkFlow,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import { X } from 'lucide-react';
|
import { X } from 'lucide-react';
|
||||||
import { useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { Button } from './ui/button';
|
import { Button } from './ui/button';
|
||||||
import { Input } from './ui/input';
|
import { Input } from './ui/input';
|
||||||
|
|
||||||
|
|||||||
191
components/script-renderer/ScriptRenderer.tsx
Normal file
191
components/script-renderer/ScriptRenderer.tsx
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
import { SquarePen, Lightbulb, Navigation, Globe, Copy, SendHorizontal } from 'lucide-react';
|
||||||
|
import { ScriptData, ScriptBlock, ScriptContent } from './types';
|
||||||
|
import ContentEditable, { ContentEditableEvent } from 'react-contenteditable';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
|
|
||||||
|
interface ScriptRendererProps {
|
||||||
|
data: ScriptData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ScriptRenderer: React.FC<ScriptRendererProps> = ({ data }) => {
|
||||||
|
const [activeBlockId, setActiveBlockId] = useState<string | null>(null);
|
||||||
|
const [hoveredBlockId, setHoveredBlockId] = useState<string | null>(null);
|
||||||
|
const contentRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
|
||||||
|
const [editBlockId, setEditBlockId] = useState<string | null>(null);
|
||||||
|
const contentEditableRef = useRef<HTMLElement>(null);
|
||||||
|
|
||||||
|
const scrollToBlock = (blockId: string) => {
|
||||||
|
const element = contentRefs.current[blockId];
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
setActiveBlockId(blockId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 用于渲染展示的 JSX
|
||||||
|
const renderContent = (content: ScriptContent) => {
|
||||||
|
switch (content.type) {
|
||||||
|
case 'heading':
|
||||||
|
return <h3 className="text-xl font-semibold mb-2">{content.text}</h3>;
|
||||||
|
case 'bold':
|
||||||
|
return <strong className="font-bold">{content.text}</strong>;
|
||||||
|
case 'italic':
|
||||||
|
return <em className="italic">{content.text}</em>;
|
||||||
|
default:
|
||||||
|
return <p className="mb-2">{content.text}</p>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 用于生成编辑时的 HTML 字符串
|
||||||
|
const contentToHtml = (content: ScriptContent): string => {
|
||||||
|
switch (content.type) {
|
||||||
|
case 'heading':
|
||||||
|
return `<h3 class="text-xl font-semibold mb-2">${content.text}</h3>`;
|
||||||
|
case 'bold':
|
||||||
|
return `<strong class="font-bold">${content.text}</strong>`;
|
||||||
|
case 'italic':
|
||||||
|
return `<em class="italic">${content.text}</em>`;
|
||||||
|
default:
|
||||||
|
return `<p class="mb-2">${content.text}</p>`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 格式化文本为 HTML
|
||||||
|
const formatTextToHtml = (text: string) => {
|
||||||
|
return text
|
||||||
|
.split('\n')
|
||||||
|
.map(line => line || '<br>')
|
||||||
|
.join('<div>');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBlockTextChange = (block: ScriptBlock) => (e: ContentEditableEvent) => {
|
||||||
|
console.log(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderEditBlock = (block: ScriptBlock) => {
|
||||||
|
let blockHtmlText = '';
|
||||||
|
block.content.forEach(item => {
|
||||||
|
blockHtmlText += contentToHtml(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ContentEditable
|
||||||
|
innerRef={contentEditableRef}
|
||||||
|
html={formatTextToHtml(blockHtmlText)}
|
||||||
|
onChange={handleBlockTextChange(block)}
|
||||||
|
className="block w-full min-h-[120px] bg-white/5 backdrop-blur-md p-4 text-white/90
|
||||||
|
rounded-lg border-unset outline-none pb-12
|
||||||
|
whitespace-pre-wrap break-words"
|
||||||
|
placeholder=""
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderBlock = (block: ScriptBlock) => {
|
||||||
|
const isHovered = hoveredBlockId === block.id;
|
||||||
|
const isActive = activeBlockId === block.id;
|
||||||
|
const isEditing = editBlockId === block.id;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
key={block.id}
|
||||||
|
className={`relative p-4 mb-1 rounded-lg shadow-md transition-colors duration-300
|
||||||
|
${isActive ? 'bg-blue-500/20' : ''} hover:bg-blue-500/10`}
|
||||||
|
ref={(el) => (contentRefs.current[block.id] = el)}
|
||||||
|
onMouseEnter={() => setHoveredBlockId(block.id)}
|
||||||
|
onMouseLeave={() => setHoveredBlockId(null)}
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
>
|
||||||
|
<h2 className="text-2xl font-semibold mb-1 text-blue-500">{block.title}</h2>
|
||||||
|
<AnimatePresence>
|
||||||
|
{(isHovered || isActive) && (
|
||||||
|
<motion.div
|
||||||
|
className="absolute top-4 right-4 flex gap-2"
|
||||||
|
initial={{ opacity: 0, y: -10 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
exit={{ opacity: 0, y: -10 }}
|
||||||
|
>
|
||||||
|
<SquarePen
|
||||||
|
className="w-6 h-6 p-1 cursor-pointer text-gray-600 hover:text-blue-500 transition-colors"
|
||||||
|
onClick={() => {
|
||||||
|
setEditBlockId(block.id);
|
||||||
|
setActiveBlockId(block.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Copy
|
||||||
|
className="w-6 h-6 p-1 cursor-pointer text-gray-600 hover:text-blue-500 transition-colors"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(block.content.map(item => item.text).join('\n'));
|
||||||
|
toast.success('Copied!');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
<div className="leading-relaxed">
|
||||||
|
{isEditing ? (
|
||||||
|
renderEditBlock(block)
|
||||||
|
) : (
|
||||||
|
block.content.map((item, index) => (
|
||||||
|
<div key={index}>{renderContent(item)}</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-full overflow-hidden pt-2">
|
||||||
|
<div className="flex-[0_0_70%] overflow-y-auto pr-4">
|
||||||
|
{data.blocks.map(renderBlock)}
|
||||||
|
</div>
|
||||||
|
<div className="flex-[0_0_30%] flex flex-col overflow-y-auto relative">
|
||||||
|
{/* 翻译功能 待开发 */}
|
||||||
|
{/* <div className="p-2 rounded-lg">
|
||||||
|
<h3 className="text-lg font-semibold mb-1 text-blue-500 flex items-center gap-1">
|
||||||
|
<Globe className="w-4 h-4 transition-colors" />
|
||||||
|
翻译
|
||||||
|
</h3>
|
||||||
|
<div className="mt-1 flex flex-col gap-2">
|
||||||
|
<select className="w-full p-2 rounded-md bg-white/5 backdrop-blur-md">
|
||||||
|
<option value="zh">中文</option>
|
||||||
|
<option value="en">英文</option>
|
||||||
|
</select>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<button className="w-full p-2 rounded-md bg-white/5 backdrop-blur-md">
|
||||||
|
翻译
|
||||||
|
</button>
|
||||||
|
<button className="w-full p-2 rounded-md bg-white/5 backdrop-blur-md">
|
||||||
|
还原
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
<div className="p-2 rounded-lg">
|
||||||
|
<h3 className="text-lg font-semibold mb-1 text-blue-500 flex items-center gap-1">
|
||||||
|
<Navigation className="w-4 h-4 transition-colors" />
|
||||||
|
导航
|
||||||
|
</h3>
|
||||||
|
{data.blocks.map((block) => (
|
||||||
|
<motion.div
|
||||||
|
key={block.id}
|
||||||
|
className={`py-1 px-1 my-1 rounded cursor-pointer transition-all duration-300 text-white/80
|
||||||
|
${activeBlockId === block.id ? 'text-blue-500/100' : 'hover:text-blue-500/80'}`}
|
||||||
|
onClick={() => scrollToBlock(block.id)}
|
||||||
|
whileHover={{ scale: 1.02 }}
|
||||||
|
whileTap={{ scale: 0.98 }}
|
||||||
|
>
|
||||||
|
{block.title}
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
76
components/script-renderer/mock.ts
Normal file
76
components/script-renderer/mock.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import { ScriptData } from './types';
|
||||||
|
|
||||||
|
export const mockScriptData: ScriptData = {
|
||||||
|
blocks: [
|
||||||
|
{
|
||||||
|
id: 'core',
|
||||||
|
title: "SCENE'S CORE CONFLICT",
|
||||||
|
type: 'core',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
text: 'The desperate, on-stage improvisation of a failing comedian triggers a physical and professional collapse, forcing him and his partner to confront the absurd meaninglessness of their ambitions. This scene serves as the inciting incident and rising action, where the internal conflict of artistic decay manifests as a literal, catastrophic failure, propelling them from a state of professional anxiety into a fight for survival.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bold',
|
||||||
|
text: 'GENRE: Satire | Absurdist Comedy | Disaster'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'scene1',
|
||||||
|
title: 'SCENE 1',
|
||||||
|
type: 'scene',
|
||||||
|
sceneNumber: 1,
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
text: 'INT. GRAND VICTORIA THEATER - NIGHT'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
text: "Scene Transition: An establishing shot of the theater's exterior: a once-magnificent building, now looking tired. A few neon characters in its name are flickering or dead. We are introduced to the world of fading glory before we even meet the characters inside."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
text: 'ACTION LINE'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
text: "The air is thick with the ghosts of applause. The GRAND VICTORIA THEATER is a cavern of faded grandeur. Ornate gold leaf peels from the balconies, and the deep red velvet seats are pocked with empty spaces. Maybe fifty people are scattered throughout an auditorium built for a thousand."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
text: "On stage, under a single, harsh SPOTLIGHT that illuminates a universe of dancing dust motes, are two men in traditional 'changshan' robes. This is a Xiangsheng (crosstalk) performance."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
text: "LIU WEI (40s), the 'Dougen' (the funny one), is sweating. His smile is a painful rictus. Beside a traditional wooden table, his partner ZHANG HAO (40s), the 'Penggen' (the straight man), stands ramrod straight, his face a mask of placid professionalism."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
text: "The audience is a mix of tourists and locals, many of whom are looking at their phones. The stage is a stage, but it's not a stage. It's a place where the audience can see the actors, but the actors can't see the audience."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'italic',
|
||||||
|
text: '(小明缓缓起身)'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'summary',
|
||||||
|
title: '总结',
|
||||||
|
type: 'summary',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
text: '故事通过展现...'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
translation: {
|
||||||
|
language: 'English',
|
||||||
|
content: 'This is a story about growth...'
|
||||||
|
}
|
||||||
|
}
|
||||||
26
components/script-renderer/types.ts
Normal file
26
components/script-renderer/types.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
export interface ScriptBlock {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
content: ScriptContent[];
|
||||||
|
type: 'core' | 'scene' | 'summary';
|
||||||
|
sceneNumber?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScriptContent {
|
||||||
|
type: 'paragraph' | 'bold' | 'italic' | 'heading';
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScriptData {
|
||||||
|
blocks: ScriptBlock[];
|
||||||
|
translation?: {
|
||||||
|
language: string;
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavigationItem {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
type: 'core' | 'scene' | 'summary';
|
||||||
|
}
|
||||||
332
package-lock.json
generated
332
package-lock.json
generated
@ -90,12 +90,14 @@
|
|||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"react-intersection-observer": "^9.16.0",
|
"react-intersection-observer": "^9.16.0",
|
||||||
"react-joyride": "^2.9.3",
|
"react-joyride": "^2.9.3",
|
||||||
|
"react-markdown": "^10.1.0",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"react-resizable": "^3.0.5",
|
"react-resizable": "^3.0.5",
|
||||||
"react-resizable-panels": "^2.1.3",
|
"react-resizable-panels": "^2.1.3",
|
||||||
"react-rough-notation": "^1.0.5",
|
"react-rough-notation": "^1.0.5",
|
||||||
"react-textarea-autosize": "^8.5.9",
|
"react-textarea-autosize": "^8.5.9",
|
||||||
"recharts": "^2.15.4",
|
"recharts": "^2.15.4",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
"sonner": "^1.5.0",
|
"sonner": "^1.5.0",
|
||||||
"styled-components": "^6.1.19",
|
"styled-components": "^6.1.19",
|
||||||
"swiper": "^11.2.8",
|
"swiper": "^11.2.8",
|
||||||
@ -12645,6 +12647,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/html-url-attributes": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/human-signals": {
|
"node_modules/human-signals": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||||
@ -14600,6 +14612,16 @@
|
|||||||
"markdown-it": "bin/markdown-it.mjs"
|
"markdown-it": "bin/markdown-it.mjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/markdown-table": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/markdown-table/-/markdown-table-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/math-intrinsics": {
|
"node_modules/math-intrinsics": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
@ -14609,6 +14631,34 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-find-and-replace": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"escape-string-regexp": "^5.0.0",
|
||||||
|
"unist-util-is": "^6.0.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-from-markdown": {
|
"node_modules/mdast-util-from-markdown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
||||||
@ -14633,6 +14683,107 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-gfm": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-gfm-autolink-literal": "^2.0.0",
|
||||||
|
"mdast-util-gfm-footnote": "^2.0.0",
|
||||||
|
"mdast-util-gfm-strikethrough": "^2.0.0",
|
||||||
|
"mdast-util-gfm-table": "^2.0.0",
|
||||||
|
"mdast-util-gfm-task-list-item": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdast-util-gfm-autolink-literal": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"ccount": "^2.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"mdast-util-find-and-replace": "^3.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdast-util-gfm-footnote": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.1.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.0.0",
|
||||||
|
"micromark-util-normalize-identifier": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdast-util-gfm-strikethrough": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdast-util-gfm-table": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"markdown-table": "^3.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdast-util-gfm-task-list-item": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-mdx": {
|
"node_modules/mdast-util-mdx": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
||||||
@ -14879,6 +15030,127 @@
|
|||||||
"micromark-util-types": "^2.0.0"
|
"micromark-util-types": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromark-extension-gfm": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"micromark-extension-gfm-autolink-literal": "^2.0.0",
|
||||||
|
"micromark-extension-gfm-footnote": "^2.0.0",
|
||||||
|
"micromark-extension-gfm-strikethrough": "^2.0.0",
|
||||||
|
"micromark-extension-gfm-table": "^2.0.0",
|
||||||
|
"micromark-extension-gfm-tagfilter": "^2.0.0",
|
||||||
|
"micromark-extension-gfm-task-list-item": "^2.0.0",
|
||||||
|
"micromark-util-combine-extensions": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-gfm-autolink-literal": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-sanitize-uri": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-gfm-footnote": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"micromark-core-commonmark": "^2.0.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-normalize-identifier": "^2.0.0",
|
||||||
|
"micromark-util-sanitize-uri": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-gfm-strikethrough": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"micromark-util-chunked": "^2.0.0",
|
||||||
|
"micromark-util-classify-character": "^2.0.0",
|
||||||
|
"micromark-util-resolve-all": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-gfm-table": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-gfm-tagfilter": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-gfm-task-list-item": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromark-extension-mdx-expression": {
|
"node_modules/micromark-extension-mdx-expression": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmmirror.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
"resolved": "https://registry.npmmirror.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
||||||
@ -17603,6 +17875,33 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-markdown": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/react-markdown/-/react-markdown-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"hast-util-to-jsx-runtime": "^2.0.0",
|
||||||
|
"html-url-attributes": "^3.0.0",
|
||||||
|
"mdast-util-to-hast": "^13.0.0",
|
||||||
|
"remark-parse": "^11.0.0",
|
||||||
|
"remark-rehype": "^11.0.0",
|
||||||
|
"unified": "^11.0.0",
|
||||||
|
"unist-util-visit": "^5.0.0",
|
||||||
|
"vfile": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": ">=18",
|
||||||
|
"react": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-redux": {
|
"node_modules/react-redux": {
|
||||||
"version": "9.2.0",
|
"version": "9.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/react-redux/-/react-redux-9.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/react-redux/-/react-redux-9.2.0.tgz",
|
||||||
@ -17989,6 +18288,24 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-gfm": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/remark-gfm/-/remark-gfm-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-gfm": "^3.0.0",
|
||||||
|
"micromark-extension-gfm": "^3.0.0",
|
||||||
|
"remark-parse": "^11.0.0",
|
||||||
|
"remark-stringify": "^11.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-mdx": {
|
"node_modules/remark-mdx": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
||||||
@ -18036,6 +18353,21 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-stringify": {
|
||||||
|
"version": "11.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/remark-stringify/-/remark-stringify-11.0.0.tgz",
|
||||||
|
"integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/require-directory": {
|
"node_modules/require-directory": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
|
"resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
|
|||||||
@ -93,12 +93,14 @@
|
|||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"react-intersection-observer": "^9.16.0",
|
"react-intersection-observer": "^9.16.0",
|
||||||
"react-joyride": "^2.9.3",
|
"react-joyride": "^2.9.3",
|
||||||
|
"react-markdown": "^10.1.0",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"react-resizable": "^3.0.5",
|
"react-resizable": "^3.0.5",
|
||||||
"react-resizable-panels": "^2.1.3",
|
"react-resizable-panels": "^2.1.3",
|
||||||
"react-rough-notation": "^1.0.5",
|
"react-rough-notation": "^1.0.5",
|
||||||
"react-textarea-autosize": "^8.5.9",
|
"react-textarea-autosize": "^8.5.9",
|
||||||
"recharts": "^2.15.4",
|
"recharts": "^2.15.4",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
"sonner": "^1.5.0",
|
"sonner": "^1.5.0",
|
||||||
"styled-components": "^6.1.19",
|
"styled-components": "^6.1.19",
|
||||||
"swiper": "^11.2.8",
|
"swiper": "^11.2.8",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user