@gendive/slide 0.1.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/README.md +55 -0
- package/dist/App.d.ts +2 -0
- package/dist/__vite-browser-external-BcPniuRQ.cjs +2 -0
- package/dist/__vite-browser-external-BcPniuRQ.cjs.map +1 -0
- package/dist/__vite-browser-external-DYxpcVy9.js +5 -0
- package/dist/__vite-browser-external-DYxpcVy9.js.map +1 -0
- package/dist/ai/components/AiEditChat.d.ts +9 -0
- package/dist/ai/components/AiImageModal.d.ts +11 -0
- package/dist/ai/components/AiPanel.d.ts +10 -0
- package/dist/ai/components/AiSlideModal.d.ts +11 -0
- package/dist/ai/components/AiTextModal.d.ts +11 -0
- package/dist/ai/components/ParsedSlideEditor.d.ts +15 -0
- package/dist/ai/hooks/useAiGeneration.d.ts +26 -0
- package/dist/ai/index.d.ts +14 -0
- package/dist/ai/services/aiApiClient.d.ts +30 -0
- package/dist/ai/services/providers/devdiveProvider.d.ts +52 -0
- package/dist/ai/services/providers/glmProvider.d.ts +26 -0
- package/dist/ai/services/providers/index.d.ts +6 -0
- package/dist/ai/services/slideDataParser.d.ts +29 -0
- package/dist/ai/stores/aiStore.d.ts +36 -0
- package/dist/ai/types/index.d.ts +154 -0
- package/dist/components/AiChatBar.d.ts +5 -0
- package/dist/components/Editor.d.ts +5 -0
- package/dist/components/FloatingToolbar.d.ts +5 -0
- package/dist/components/Header.d.ts +5 -0
- package/dist/components/ImageNode.d.ts +15 -0
- package/dist/components/PropertiesPanel.d.ts +5 -0
- package/dist/components/ShapeNode.d.ts +25 -0
- package/dist/components/SlideCanvas.d.ts +4 -0
- package/dist/components/SlideNavigation.d.ts +5 -0
- package/dist/components/SlideThumbnails.d.ts +5 -0
- package/dist/components/TemplateGallery.d.ts +11 -0
- package/dist/components/TextNode.d.ts +14 -0
- package/dist/data/templates.d.ts +9 -0
- package/dist/devdive-slide.cjs.js +469 -0
- package/dist/devdive-slide.cjs.js.map +1 -0
- package/dist/devdive-slide.es.js +32580 -0
- package/dist/devdive-slide.es.js.map +1 -0
- package/dist/hooks/useAutoSave.d.ts +28 -0
- package/dist/hooks/useKeyboardShortcuts.d.ts +4 -0
- package/dist/index.d.ts +19 -0
- package/dist/lib/pptxGenerator.d.ts +5 -0
- package/dist/lib/storage/adapters/hybridAdapter.d.ts +19 -0
- package/dist/lib/storage/adapters/index.d.ts +7 -0
- package/dist/lib/storage/adapters/indexedDBAdapter.d.ts +17 -0
- package/dist/lib/storage/adapters/serverAdapter.d.ts +6 -0
- package/dist/lib/storage/index.d.ts +7 -0
- package/dist/lib/storage/storageService.d.ts +52 -0
- package/dist/lib/storage/types.d.ts +41 -0
- package/dist/main.d.ts +0 -0
- package/dist/slide.css +1 -0
- package/dist/stores/editorStore.d.ts +26 -0
- package/dist/theme/index.d.ts +154 -0
- package/dist/types/index.d.ts +202 -0
- package/dist/utils/id.d.ts +5 -0
- package/dist/utils/markdown.d.ts +29 -0
- package/dist/utils/snap.d.ts +20 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# DevDive Slide
|
|
2
|
+
|
|
3
|
+
React 기반 프레젠테이션 에디터 라이브러리. Canva 스타일의 이미지 크롭, PPTX 내보내기를 지원합니다.
|
|
4
|
+
|
|
5
|
+
## 주요 기능
|
|
6
|
+
|
|
7
|
+
- **텍스트 편집** - 마크다운 지원, 다양한 텍스트 스타일 (제목/소제목/본문/캡션)
|
|
8
|
+
- **도형** - 사각형, 원, 삼각형, 선, 화살표 + 내부 텍스트
|
|
9
|
+
- **이미지** - 드래그 앤 드롭, Canva 스타일 크롭, 확대/축소
|
|
10
|
+
- **템플릿** - 다양한 레이아웃 및 테마 프리셋
|
|
11
|
+
- **PPTX 내보내기** - 모든 요소를 PowerPoint로 변환
|
|
12
|
+
|
|
13
|
+
## 설치
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 개발 서버
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm dev
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 라이브러리 빌드
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm build:lib
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 기술 스택
|
|
32
|
+
|
|
33
|
+
- **React 19** + **TypeScript 5.6**
|
|
34
|
+
- **Vite** - 빌드 도구
|
|
35
|
+
- **Zustand** - 상태 관리
|
|
36
|
+
- **Konva** / **react-konva** - 캔버스 렌더링
|
|
37
|
+
- **PptxGenJS** - PPTX 생성
|
|
38
|
+
- **Tailwind CSS 4** - 스타일링
|
|
39
|
+
|
|
40
|
+
## 사용법
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { Editor, useEditorStore } from '@devdive/slide';
|
|
44
|
+
import '@devdive/slide/style.css';
|
|
45
|
+
|
|
46
|
+
function App() {
|
|
47
|
+
return <Editor />;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 라이선스
|
|
52
|
+
|
|
53
|
+
© DevDive. All rights reserved.
|
|
54
|
+
|
|
55
|
+
이 소프트웨어는 DevDive의 독점 소유물입니다. 명시적인 서면 허가 없이 복제, 수정, 배포할 수 없습니다.
|
package/dist/App.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"__vite-browser-external-BcPniuRQ.cjs","sources":["../__vite-browser-external"],"sourcesContent":["export default {}"],"names":["__viteBrowserExternal"],"mappings":"gFAAA,MAAAA,EAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"__vite-browser-external-DYxpcVy9.js","sources":["../__vite-browser-external"],"sourcesContent":["export default {}"],"names":["__viteBrowserExternal"],"mappings":"AAAA,MAAAA,IAAe,CAAA;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface AiImageModalProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
onBack: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* @description AI 이미지 생성 모달
|
|
8
|
+
* @Todo vibecode - 프롬프트로 이미지 생성
|
|
9
|
+
*/
|
|
10
|
+
export declare const AiImageModal: ({ isOpen, onClose, onBack }: AiImageModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface AiPanelProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* @description AI 기능 선택 패널
|
|
7
|
+
* @Todo vibecode - AI 기능 진입점
|
|
8
|
+
*/
|
|
9
|
+
export declare const AiPanel: ({ isOpen, onClose }: AiPanelProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface AiSlideModalProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
onBack: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* @description AI 슬라이드 자동 생성 모달
|
|
8
|
+
* @Todo vibecode - 2단계 프로세스: 구조 생성 → 콘텐츠 생성
|
|
9
|
+
*/
|
|
10
|
+
export declare const AiSlideModal: ({ isOpen, onClose, onBack }: AiSlideModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface AiTextModalProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
onBack: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* @description AI 텍스트 생성 모달
|
|
8
|
+
* @Todo vibecode - 프롬프트로 텍스트 생성
|
|
9
|
+
*/
|
|
10
|
+
export declare const AiTextModal: ({ isOpen, onClose, onBack }: AiTextModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ParsedSlideData } from '../services/slideDataParser';
|
|
2
|
+
interface ParsedSlideEditorProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
slide: ParsedSlideData;
|
|
6
|
+
slideIndex: number;
|
|
7
|
+
onSave: (index: number, updated: ParsedSlideData) => void;
|
|
8
|
+
onDelete: (index: number) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @description 파싱된 슬라이드 개별 편집 모달
|
|
12
|
+
* @Todo vibecode - 슬라이드별 수정 UI
|
|
13
|
+
*/
|
|
14
|
+
export declare const ParsedSlideEditor: ({ isOpen, onClose, slide, slideIndex, onSave, onDelete, }: ParsedSlideEditorProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SlideContentRequest } from '../services/providers/devdiveProvider';
|
|
2
|
+
import { AiTextRequest, AiSlideGenerationRequest, AiImageRequest, AiImageResponse, AiDesignRequest, AiDesignSuggestion, AiGeneratedSlide } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* @description AI 생성 기능 훅
|
|
5
|
+
* @Todo vibecode - 제공자별 API 호출 및 상태 관리 통합
|
|
6
|
+
*/
|
|
7
|
+
export declare const useAiGeneration: () => {
|
|
8
|
+
status: import('..').AiRequestStatus;
|
|
9
|
+
currentFeature: import('..').AiFeatureType | null;
|
|
10
|
+
error: string | null;
|
|
11
|
+
isLoading: boolean;
|
|
12
|
+
isSuccess: boolean;
|
|
13
|
+
isError: boolean;
|
|
14
|
+
providerConfig: import('..').AiProviderConfig | null;
|
|
15
|
+
setProviderConfig: (config: import('..').AiProviderConfig | null) => void;
|
|
16
|
+
lastTextResponse: import('..').AiTextResponse | null;
|
|
17
|
+
lastSlideResponse: import('..').AiSlideGenerationResponse | null;
|
|
18
|
+
lastImageResponse: AiImageResponse | null;
|
|
19
|
+
lastDesignSuggestions: AiDesignSuggestion[] | null;
|
|
20
|
+
generateText: (request: AiTextRequest) => Promise<import('..').AiTextResponse>;
|
|
21
|
+
generateSlides: (request: AiSlideGenerationRequest) => Promise<import('..').AiSlideGenerationResponse>;
|
|
22
|
+
generateSlideContent: (request: SlideContentRequest) => Promise<AiGeneratedSlide>;
|
|
23
|
+
generateImage: (_request: AiImageRequest) => Promise<AiImageResponse>;
|
|
24
|
+
suggestDesign: (_request: AiDesignRequest) => Promise<AiDesignSuggestion[]>;
|
|
25
|
+
reset: () => void;
|
|
26
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description AI 모듈 export
|
|
3
|
+
* @Todo vibecode - AI 관련 기능 통합 export
|
|
4
|
+
*/
|
|
5
|
+
export * from './types';
|
|
6
|
+
export { useAiStore } from './stores/aiStore';
|
|
7
|
+
export { useAiGeneration } from './hooks/useAiGeneration';
|
|
8
|
+
export { glmProvider, GlmApiError } from './services/providers';
|
|
9
|
+
export { parseSlideData, createSlideElements, mapToInternalLayout } from './services/slideDataParser';
|
|
10
|
+
export type { ParsedSlideData } from './services/slideDataParser';
|
|
11
|
+
export { AiPanel } from './components/AiPanel';
|
|
12
|
+
export { AiTextModal } from './components/AiTextModal';
|
|
13
|
+
export { AiSlideModal } from './components/AiSlideModal';
|
|
14
|
+
export { AiImageModal } from './components/AiImageModal';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AiTextRequest, AiTextResponse, AiSlideGenerationRequest, AiSlideGenerationResponse, AiImageRequest, AiImageResponse, AiDesignRequest, AiDesignSuggestion } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* @description API 에러 클래스
|
|
4
|
+
*/
|
|
5
|
+
export declare class AiApiError extends Error {
|
|
6
|
+
statusCode?: number | undefined;
|
|
7
|
+
constructor(message: string, statusCode?: number | undefined);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* @description AI API 클라이언트
|
|
11
|
+
* @Todo vibecode - 백엔드 프록시 API 호출
|
|
12
|
+
*/
|
|
13
|
+
export declare const aiApiClient: {
|
|
14
|
+
/**
|
|
15
|
+
* @description 텍스트 생성
|
|
16
|
+
*/
|
|
17
|
+
generateText: (request: AiTextRequest) => Promise<AiTextResponse>;
|
|
18
|
+
/**
|
|
19
|
+
* @description 슬라이드 자동 생성
|
|
20
|
+
*/
|
|
21
|
+
generateSlides: (request: AiSlideGenerationRequest) => Promise<AiSlideGenerationResponse>;
|
|
22
|
+
/**
|
|
23
|
+
* @description 이미지 생성
|
|
24
|
+
*/
|
|
25
|
+
generateImage: (request: AiImageRequest) => Promise<AiImageResponse>;
|
|
26
|
+
/**
|
|
27
|
+
* @description 디자인 제안
|
|
28
|
+
*/
|
|
29
|
+
suggestDesign: (request: AiDesignRequest) => Promise<AiDesignSuggestion[]>;
|
|
30
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { AiTextRequest, AiTextResponse, AiSlideGenerationRequest, AiSlideGenerationResponse, AiGeneratedSlide, DevDiveConfig } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* @description DevDive API 에러
|
|
4
|
+
*/
|
|
5
|
+
export declare class DevDiveApiError extends Error {
|
|
6
|
+
code?: string | undefined;
|
|
7
|
+
status?: number | undefined;
|
|
8
|
+
constructor(message: string, code?: string | undefined, status?: number | undefined);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @description 텍스트 생성
|
|
12
|
+
* @Todo vibecode - DevDive GPT-4o 텍스트 생성
|
|
13
|
+
*/
|
|
14
|
+
export declare const generateTextWithDevDive: (request: AiTextRequest, config: DevDiveConfig) => Promise<AiTextResponse>;
|
|
15
|
+
/**
|
|
16
|
+
* @description 슬라이드 자동 생성
|
|
17
|
+
* @Todo vibecode - DevDive GPT-4o 슬라이드 생성
|
|
18
|
+
*/
|
|
19
|
+
export declare const generateSlidesWithDevDive: (request: AiSlideGenerationRequest, config: DevDiveConfig) => Promise<AiSlideGenerationResponse>;
|
|
20
|
+
/**
|
|
21
|
+
* @description 슬라이드 구조 요청 타입
|
|
22
|
+
*/
|
|
23
|
+
export interface SlideStructureItem {
|
|
24
|
+
index: number;
|
|
25
|
+
layout: string;
|
|
26
|
+
purpose: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @description 슬라이드 콘텐츠 생성 요청 타입
|
|
30
|
+
*/
|
|
31
|
+
export interface SlideContentRequest {
|
|
32
|
+
topic: string;
|
|
33
|
+
slideIndex: number;
|
|
34
|
+
totalSlides: number;
|
|
35
|
+
layout: string;
|
|
36
|
+
purpose: string;
|
|
37
|
+
style: string;
|
|
38
|
+
language: 'ko' | 'en';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* @description 개별 슬라이드 콘텐츠 생성
|
|
42
|
+
* @Todo vibecode - IR 스타일 프롬프트로 슬라이드별 콘텐츠 생성
|
|
43
|
+
*/
|
|
44
|
+
export declare const generateSlideContentWithDevDive: (request: SlideContentRequest, config: DevDiveConfig) => Promise<AiGeneratedSlide>;
|
|
45
|
+
/**
|
|
46
|
+
* @description DevDive Provider
|
|
47
|
+
*/
|
|
48
|
+
export declare const devdiveProvider: {
|
|
49
|
+
generateText: (request: AiTextRequest, config: DevDiveConfig) => Promise<AiTextResponse>;
|
|
50
|
+
generateSlides: (request: AiSlideGenerationRequest, config: DevDiveConfig) => Promise<AiSlideGenerationResponse>;
|
|
51
|
+
generateSlideContent: (request: SlideContentRequest, config: DevDiveConfig) => Promise<AiGeneratedSlide>;
|
|
52
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AiTextRequest, AiTextResponse, AiSlideGenerationRequest, AiSlideGenerationResponse, GlmConfig } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* @description GLM API 에러
|
|
4
|
+
*/
|
|
5
|
+
export declare class GlmApiError extends Error {
|
|
6
|
+
code?: string | undefined;
|
|
7
|
+
status?: number | undefined;
|
|
8
|
+
constructor(message: string, code?: string | undefined, status?: number | undefined);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @description 텍스트 생성
|
|
12
|
+
* @Todo vibecode - GLM-4.7 텍스트 생성
|
|
13
|
+
*/
|
|
14
|
+
export declare const generateTextWithGlm: (request: AiTextRequest, config: GlmConfig) => Promise<AiTextResponse>;
|
|
15
|
+
/**
|
|
16
|
+
* @description 슬라이드 자동 생성
|
|
17
|
+
* @Todo vibecode - GLM-4.7 슬라이드 생성
|
|
18
|
+
*/
|
|
19
|
+
export declare const generateSlidesWithGlm: (request: AiSlideGenerationRequest, config: GlmConfig) => Promise<AiSlideGenerationResponse>;
|
|
20
|
+
/**
|
|
21
|
+
* @description GLM Provider
|
|
22
|
+
*/
|
|
23
|
+
export declare const glmProvider: {
|
|
24
|
+
generateText: (request: AiTextRequest, config: GlmConfig) => Promise<AiTextResponse>;
|
|
25
|
+
generateSlides: (request: AiSlideGenerationRequest, config: GlmConfig) => Promise<AiSlideGenerationResponse>;
|
|
26
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { LayoutType, ThemeColors, TextElement, ShapeElement } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* @description 파싱된 슬라이드 데이터
|
|
4
|
+
*/
|
|
5
|
+
export interface ParsedSlideData {
|
|
6
|
+
slideNumber: string;
|
|
7
|
+
sectionType: string;
|
|
8
|
+
recommendedLayout: string;
|
|
9
|
+
visualElements: string;
|
|
10
|
+
layoutReason: string;
|
|
11
|
+
sectionTitle: string;
|
|
12
|
+
summary: string;
|
|
13
|
+
keyPoints: string[];
|
|
14
|
+
keywords: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* @description 구조화된 텍스트 데이터 파싱
|
|
18
|
+
* @Todo vibecode - [태그] 값 형식의 데이터 파싱
|
|
19
|
+
*/
|
|
20
|
+
export declare const parseSlideData: (rawText: string) => ParsedSlideData[];
|
|
21
|
+
/**
|
|
22
|
+
* @description 레이아웃 매핑
|
|
23
|
+
*/
|
|
24
|
+
export declare const mapToInternalLayout: (externalLayout: string) => LayoutType;
|
|
25
|
+
/**
|
|
26
|
+
* @description 파싱된 데이터로 슬라이드 요소 생성
|
|
27
|
+
* @Todo vibecode - 레이아웃에 따라 적절한 요소 배치 + 시각적 요소 추가 + 이미지 플레이스홀더
|
|
28
|
+
*/
|
|
29
|
+
export declare const createSlideElements: (data: ParsedSlideData, theme?: ThemeColors) => (TextElement | ShapeElement)[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { AiState, AiActions, AiProviderConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* @description AI 제공자 설정 상태
|
|
4
|
+
*/
|
|
5
|
+
interface AiProviderState {
|
|
6
|
+
providerConfig: AiProviderConfig | null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* @description AI 제공자 설정 액션
|
|
10
|
+
*/
|
|
11
|
+
interface AiProviderActions {
|
|
12
|
+
setProviderConfig: (config: AiProviderConfig | null) => void;
|
|
13
|
+
getProviderConfig: () => AiProviderConfig | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @description AI 상태 관리 스토어
|
|
17
|
+
* @Todo vibecode - Zustand 기반 AI 상태 관리 + 제공자 설정
|
|
18
|
+
*/
|
|
19
|
+
export declare const useAiStore: import('zustand').UseBoundStore<Omit<import('zustand').StoreApi<AiState & AiActions & AiProviderState & AiProviderActions>, "setState" | "persist"> & {
|
|
20
|
+
setState(partial: (AiState & AiActions & AiProviderState & AiProviderActions) | Partial<AiState & AiActions & AiProviderState & AiProviderActions> | ((state: AiState & AiActions & AiProviderState & AiProviderActions) => (AiState & AiActions & AiProviderState & AiProviderActions) | Partial<AiState & AiActions & AiProviderState & AiProviderActions>), replace?: false | undefined): unknown;
|
|
21
|
+
setState(state: (AiState & AiActions & AiProviderState & AiProviderActions) | ((state: AiState & AiActions & AiProviderState & AiProviderActions) => AiState & AiActions & AiProviderState & AiProviderActions), replace: true): unknown;
|
|
22
|
+
persist: {
|
|
23
|
+
setOptions: (options: Partial<import('zustand/middleware').PersistOptions<AiState & AiActions & AiProviderState & AiProviderActions, {
|
|
24
|
+
providerConfig: AiProviderConfig | null;
|
|
25
|
+
}, unknown>>) => void;
|
|
26
|
+
clearStorage: () => void;
|
|
27
|
+
rehydrate: () => Promise<void> | void;
|
|
28
|
+
hasHydrated: () => boolean;
|
|
29
|
+
onHydrate: (fn: (state: AiState & AiActions & AiProviderState & AiProviderActions) => void) => () => void;
|
|
30
|
+
onFinishHydration: (fn: (state: AiState & AiActions & AiProviderState & AiProviderActions) => void) => () => void;
|
|
31
|
+
getOptions: () => Partial<import('zustand/middleware').PersistOptions<AiState & AiActions & AiProviderState & AiProviderActions, {
|
|
32
|
+
providerConfig: AiProviderConfig | null;
|
|
33
|
+
}, unknown>>;
|
|
34
|
+
};
|
|
35
|
+
}>;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Slide, LayoutType, ThemeColors, TextStyleType } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* @description AI 제공자 타입
|
|
4
|
+
* @Todo vibecode - 지원하는 AI 서비스
|
|
5
|
+
*/
|
|
6
|
+
export type AiProviderType = 'devdive' | 'glm' | 'openai' | 'claude' | 'custom';
|
|
7
|
+
/**
|
|
8
|
+
* @description AI 제공자 설정
|
|
9
|
+
* @Todo vibecode - 각 제공자별 설정
|
|
10
|
+
*/
|
|
11
|
+
export interface AiProviderConfig {
|
|
12
|
+
provider: AiProviderType;
|
|
13
|
+
apiKey: string;
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @description GLM 설정
|
|
19
|
+
*/
|
|
20
|
+
export interface GlmConfig extends AiProviderConfig {
|
|
21
|
+
provider: 'glm';
|
|
22
|
+
model?: 'glm-4.7' | 'glm-4' | 'glm-4-flash' | 'glm-4v';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @description OpenAI 설정
|
|
26
|
+
*/
|
|
27
|
+
export interface OpenAiConfig extends AiProviderConfig {
|
|
28
|
+
provider: 'openai';
|
|
29
|
+
model?: 'gpt-4' | 'gpt-4-turbo' | 'gpt-3.5-turbo';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @description Claude 설정
|
|
33
|
+
*/
|
|
34
|
+
export interface ClaudeConfig extends AiProviderConfig {
|
|
35
|
+
provider: 'claude';
|
|
36
|
+
model?: 'claude-3-opus' | 'claude-3-sonnet' | 'claude-3-haiku';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* @description DevDive 설정
|
|
40
|
+
* @Todo vibecode - DevDive AI 플랫폼 설정
|
|
41
|
+
*/
|
|
42
|
+
export interface DevDiveConfig extends AiProviderConfig {
|
|
43
|
+
provider: 'devdive';
|
|
44
|
+
model?: 'gpt-4o' | 'gpt-4o-mini' | 'claude-3-5-sonnet';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* @description AI 기능 타입
|
|
48
|
+
* @Todo vibecode - AI 모듈 타입 정의
|
|
49
|
+
*/
|
|
50
|
+
export type AiFeatureType = 'text' | 'slide' | 'image' | 'design';
|
|
51
|
+
/**
|
|
52
|
+
* @description AI 요청 상태
|
|
53
|
+
*/
|
|
54
|
+
export type AiRequestStatus = 'idle' | 'loading' | 'success' | 'error';
|
|
55
|
+
/**
|
|
56
|
+
* @description 텍스트 생성 요청
|
|
57
|
+
*/
|
|
58
|
+
export interface AiTextRequest {
|
|
59
|
+
prompt: string;
|
|
60
|
+
style: TextStyleType;
|
|
61
|
+
language?: 'ko' | 'en';
|
|
62
|
+
maxLength?: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* @description 텍스트 생성 응답
|
|
66
|
+
*/
|
|
67
|
+
export interface AiTextResponse {
|
|
68
|
+
content: string;
|
|
69
|
+
alternatives?: string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* @description 슬라이드 자동 생성 요청
|
|
73
|
+
*/
|
|
74
|
+
export interface AiSlideGenerationRequest {
|
|
75
|
+
topic: string;
|
|
76
|
+
slideCount: number;
|
|
77
|
+
style: 'business' | 'creative' | 'minimal' | 'educational';
|
|
78
|
+
includeImages: boolean;
|
|
79
|
+
language?: 'ko' | 'en';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* @description 생성된 슬라이드 구조
|
|
83
|
+
*/
|
|
84
|
+
export interface AiGeneratedSlide {
|
|
85
|
+
layout: LayoutType;
|
|
86
|
+
title?: string;
|
|
87
|
+
subtitle?: string;
|
|
88
|
+
content?: string;
|
|
89
|
+
bulletPoints?: string[];
|
|
90
|
+
imagePrompt?: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* @description 슬라이드 생성 응답
|
|
94
|
+
*/
|
|
95
|
+
export interface AiSlideGenerationResponse {
|
|
96
|
+
slides: AiGeneratedSlide[];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* @description 이미지 생성 요청
|
|
100
|
+
*/
|
|
101
|
+
export interface AiImageRequest {
|
|
102
|
+
prompt: string;
|
|
103
|
+
style: 'realistic' | 'illustration' | 'abstract' | '3d' | 'minimalist';
|
|
104
|
+
size: '512x512' | '1024x1024';
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* @description 이미지 생성 응답
|
|
108
|
+
*/
|
|
109
|
+
export interface AiImageResponse {
|
|
110
|
+
imageUrl: string;
|
|
111
|
+
base64?: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* @description 디자인 제안 요청
|
|
115
|
+
*/
|
|
116
|
+
export interface AiDesignRequest {
|
|
117
|
+
currentSlide: Slide;
|
|
118
|
+
suggestionType: 'layout' | 'color' | 'typography' | 'all';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* @description 디자인 제안 응답
|
|
122
|
+
*/
|
|
123
|
+
export interface AiDesignSuggestion {
|
|
124
|
+
id: string;
|
|
125
|
+
type: 'layout' | 'color' | 'typography';
|
|
126
|
+
description: string;
|
|
127
|
+
preview?: ThemeColors;
|
|
128
|
+
layoutId?: LayoutType;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* @description AI 스토어 상태
|
|
132
|
+
*/
|
|
133
|
+
export interface AiState {
|
|
134
|
+
status: AiRequestStatus;
|
|
135
|
+
currentFeature: AiFeatureType | null;
|
|
136
|
+
error: string | null;
|
|
137
|
+
lastTextResponse: AiTextResponse | null;
|
|
138
|
+
lastSlideResponse: AiSlideGenerationResponse | null;
|
|
139
|
+
lastImageResponse: AiImageResponse | null;
|
|
140
|
+
lastDesignSuggestions: AiDesignSuggestion[] | null;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @description AI 스토어 액션
|
|
144
|
+
*/
|
|
145
|
+
export interface AiActions {
|
|
146
|
+
setStatus: (status: AiRequestStatus) => void;
|
|
147
|
+
setFeature: (feature: AiFeatureType | null) => void;
|
|
148
|
+
setError: (error: string | null) => void;
|
|
149
|
+
setTextResponse: (response: AiTextResponse | null) => void;
|
|
150
|
+
setSlideResponse: (response: AiSlideGenerationResponse | null) => void;
|
|
151
|
+
setImageResponse: (response: AiImageResponse | null) => void;
|
|
152
|
+
setDesignSuggestions: (suggestions: AiDesignSuggestion[] | null) => void;
|
|
153
|
+
reset: () => void;
|
|
154
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ImageElement } from '../types';
|
|
2
|
+
interface ImageNodeProps {
|
|
3
|
+
element: ImageElement;
|
|
4
|
+
isSelected: boolean;
|
|
5
|
+
onSelect: () => void;
|
|
6
|
+
onChange: (updates: Partial<ImageElement>, isDragging?: boolean) => void;
|
|
7
|
+
onDragStart?: () => void;
|
|
8
|
+
onDragEnd?: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @description 이미지 요소 렌더링 컴포넌트
|
|
12
|
+
* @Todo vibecode - 중심 회전, 곡률, 크롭 편집 지원
|
|
13
|
+
*/
|
|
14
|
+
export declare const ImageNode: ({ element, isSelected, onSelect, onChange, onDragStart, onDragEnd: onDragEndCallback }: ImageNodeProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ShapeElement } from '../types';
|
|
2
|
+
interface ShapeNodeProps {
|
|
3
|
+
element: ShapeElement;
|
|
4
|
+
isSelected: boolean;
|
|
5
|
+
onSelect: () => void;
|
|
6
|
+
onChange: (updates: Partial<ShapeElement>, isDragging?: boolean) => void;
|
|
7
|
+
onDragStart?: () => void;
|
|
8
|
+
onDragEnd?: () => void;
|
|
9
|
+
onReplaceWithImage?: (imageData: {
|
|
10
|
+
src: string;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
crop?: {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
19
|
+
}) => void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @description 도형 요소 렌더링 컴포넌트 (텍스트 지원)
|
|
23
|
+
*/
|
|
24
|
+
export declare const ShapeNode: ({ element, isSelected, onSelect, onChange, onDragStart, onDragEnd: onDragEndCallback, onReplaceWithImage }: ShapeNodeProps) => import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface TemplateGalleryProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
mode: 'apply' | 'new';
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* @description 템플릿 갤러리 모달 컴포넌트
|
|
8
|
+
* @Todo vibecode - Tailwind → Mantine 마이그레이션 완료
|
|
9
|
+
*/
|
|
10
|
+
export declare const TemplateGallery: ({ isOpen, onClose, mode }: TemplateGalleryProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TextElement } from '../types';
|
|
2
|
+
interface TextNodeProps {
|
|
3
|
+
element: TextElement;
|
|
4
|
+
isSelected: boolean;
|
|
5
|
+
onSelect: () => void;
|
|
6
|
+
onChange: (updates: Partial<TextElement>, isDragging?: boolean) => void;
|
|
7
|
+
onDragStart?: () => void;
|
|
8
|
+
onDragEnd?: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @description 텍스트 요소 렌더링 컴포넌트 (더블클릭 편집 지원)
|
|
12
|
+
*/
|
|
13
|
+
export declare const TextNode: ({ element, isSelected, onSelect, onChange, onDragStart, onDragEnd }: TextNodeProps) => import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|