@qwanyx/ai-editor 1.3.13 → 1.4.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.
Files changed (46) hide show
  1. package/dist/components/PageEditor.d.ts +10 -0
  2. package/dist/components/PageEditor.d.ts.map +1 -0
  3. package/dist/components/PageEditor.js +294 -0
  4. package/dist/components/PageViewer.d.ts +8 -0
  5. package/dist/components/PageViewer.d.ts.map +1 -0
  6. package/dist/components/PageViewer.js +38 -0
  7. package/dist/components/RichTextEditor.d.ts +5 -1
  8. package/dist/components/RichTextEditor.d.ts.map +1 -1
  9. package/dist/components/RichTextEditor.js +11 -2
  10. package/dist/components/RichTextViewer.d.ts +3 -1
  11. package/dist/components/RichTextViewer.d.ts.map +1 -1
  12. package/dist/components/RichTextViewer.js +7 -2
  13. package/dist/components/Section.d.ts +10 -0
  14. package/dist/components/Section.d.ts.map +1 -0
  15. package/dist/components/Section.js +117 -0
  16. package/dist/components/SmartEditor.d.ts +58 -0
  17. package/dist/components/SmartEditor.d.ts.map +1 -0
  18. package/dist/components/SmartEditor.js +123 -0
  19. package/dist/context/PageContext.d.ts +35 -0
  20. package/dist/context/PageContext.d.ts.map +1 -0
  21. package/dist/context/PageContext.js +277 -0
  22. package/dist/index.d.ts +17 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +54 -1
  25. package/dist/layouts/OgilvyLayout.d.ts +5 -0
  26. package/dist/layouts/OgilvyLayout.d.ts.map +1 -0
  27. package/dist/layouts/OgilvyLayout.js +301 -0
  28. package/dist/layouts/RichTextLayout.d.ts +7 -0
  29. package/dist/layouts/RichTextLayout.d.ts.map +1 -0
  30. package/dist/layouts/RichTextLayout.js +47 -0
  31. package/dist/layouts/index.d.ts +30 -0
  32. package/dist/layouts/index.d.ts.map +1 -0
  33. package/dist/layouts/index.js +71 -0
  34. package/dist/types/index.d.ts +5 -0
  35. package/dist/types/index.d.ts.map +1 -0
  36. package/dist/types/index.js +20 -0
  37. package/dist/types/page.d.ts +151 -0
  38. package/dist/types/page.d.ts.map +1 -0
  39. package/dist/types/page.js +54 -0
  40. package/dist/utils/format.d.ts +71 -0
  41. package/dist/utils/format.d.ts.map +1 -0
  42. package/dist/utils/format.js +190 -0
  43. package/dist/utils/index.d.ts +5 -0
  44. package/dist/utils/index.d.ts.map +1 -0
  45. package/dist/utils/index.js +20 -0
  46. package/package.json +1 -1
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /**
3
+ * Types pour le système de Pages et Sections
4
+ * Extension de qwanyx-ai-editor
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.DEFAULT_DROP_CAP = exports.VIDEO_PRESETS = exports.PRINT_PRESETS = void 0;
8
+ exports.generateId = generateId;
9
+ exports.createSection = createSection;
10
+ exports.createEmptyPage = createEmptyPage;
11
+ // Presets communs
12
+ exports.PRINT_PRESETS = {
13
+ A4: { width: 210, height: 297, unit: 'mm', name: 'A4' },
14
+ A3: { width: 297, height: 420, unit: 'mm', name: 'A3' },
15
+ Letter: { width: 8.5, height: 11, unit: 'in', name: 'Letter' },
16
+ Legal: { width: 8.5, height: 14, unit: 'in', name: 'Legal' },
17
+ };
18
+ exports.VIDEO_PRESETS = {
19
+ 'Full HD': { width: 1920, height: 1080, name: 'Full HD (16:9)' },
20
+ '4K': { width: 3840, height: 2160, name: '4K UHD (16:9)' },
21
+ 'HD': { width: 1280, height: 720, name: 'HD (16:9)' },
22
+ 'Square': { width: 1080, height: 1080, name: 'Carré (1:1)' },
23
+ 'Portrait': { width: 1080, height: 1920, name: 'Portrait (9:16)' },
24
+ '4:3': { width: 1024, height: 768, name: 'Standard (4:3)' },
25
+ };
26
+ exports.DEFAULT_DROP_CAP = {
27
+ enabled: true,
28
+ type: 'letter',
29
+ fontSize: 3,
30
+ lineHeight: 3,
31
+ };
32
+ // ============================================
33
+ // Helpers
34
+ // ============================================
35
+ function generateId() {
36
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
37
+ }
38
+ function createSection(layoutType, content, animation) {
39
+ return {
40
+ id: generateId(),
41
+ layoutType,
42
+ content,
43
+ animation,
44
+ };
45
+ }
46
+ function createEmptyPage(format = 'web') {
47
+ return {
48
+ id: generateId(),
49
+ format,
50
+ sections: [],
51
+ createdAt: new Date().toISOString(),
52
+ updatedAt: new Date().toISOString(),
53
+ };
54
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Utilitaires pour la détection et conversion de formats
3
+ *
4
+ * Gère la rétrocompatibilité entre:
5
+ * - Ancien format: JSON Lexical brut (string)
6
+ * - Nouveau format: PageDocument avec sections
7
+ */
8
+ import { PageDocument } from '../types/page';
9
+ export type ContentFormat = 'lexical' | 'page-document' | 'empty' | 'unknown';
10
+ export interface FormatDetectionResult {
11
+ format: ContentFormat;
12
+ data: PageDocument | string | null;
13
+ }
14
+ /**
15
+ * Détecte le format du contenu
16
+ *
17
+ * @param content - Le contenu à analyser (string JSON ou objet)
18
+ * @returns Le type de format détecté et les données parsées
19
+ */
20
+ export declare function detectFormat(content: string | PageDocument | null | undefined): FormatDetectionResult;
21
+ /**
22
+ * Vérifie si un objet est un PageDocument valide
23
+ */
24
+ export declare function isPageDocument(obj: unknown): obj is PageDocument;
25
+ /**
26
+ * Vérifie si un objet est un état Lexical valide
27
+ */
28
+ export declare function isLexicalState(obj: unknown): boolean;
29
+ /**
30
+ * Convertit du contenu Lexical brut en PageDocument
31
+ * Crée une page avec une seule section "text-only" contenant l'éditeur
32
+ *
33
+ * @param lexicalContent - Le JSON Lexical (string ou objet)
34
+ * @param format - Le format de page souhaité (défaut: 'web')
35
+ * @returns Un PageDocument avec le contenu Lexical dans une section
36
+ */
37
+ export declare function lexicalToPageDocument(lexicalContent: string | object, format?: 'web' | 'print' | 'video'): PageDocument;
38
+ /**
39
+ * Extrait le contenu Lexical d'un PageDocument
40
+ * Si le document a une seule section "text-only", retourne le Lexical brut
41
+ * Sinon, retourne null (le document utilise le nouveau format)
42
+ *
43
+ * @param document - Le PageDocument à analyser
44
+ * @returns Le JSON Lexical si applicable, sinon null
45
+ */
46
+ export declare function pageDocumentToLexical(document: PageDocument): string | null;
47
+ /**
48
+ * Convertit automatiquement le contenu vers PageDocument si nécessaire
49
+ *
50
+ * @param content - Le contenu (peut être Lexical ou PageDocument)
51
+ * @returns Un PageDocument valide
52
+ */
53
+ export declare function ensurePageDocument(content: string | PageDocument | null | undefined): PageDocument;
54
+ /**
55
+ * Vérifie si un PageDocument est "simple" (une seule section text-only)
56
+ * Utile pour décider comment sauvegarder
57
+ */
58
+ export declare function isSimpleDocument(document: PageDocument): boolean;
59
+ export interface SaveOptions {
60
+ /** Si true, sauvegarde en Lexical brut si possible (rétrocompatibilité) */
61
+ preferLegacyFormat?: boolean;
62
+ }
63
+ /**
64
+ * Prépare le contenu pour la sauvegarde
65
+ *
66
+ * @param document - Le PageDocument à sauvegarder
67
+ * @param options - Options de sauvegarde
68
+ * @returns String JSON à sauvegarder
69
+ */
70
+ export declare function prepareForSave(document: PageDocument, options?: SaveOptions): string;
71
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EAIb,MAAM,eAAe,CAAA;AAOtB,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,eAAe,GAAG,OAAO,GAAG,SAAS,CAAA;AAE7E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,aAAa,CAAA;IACrB,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAAA;CACnC;AAMD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,qBAAqB,CA4CrG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,YAAY,CAahE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAYpD;AAMD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,GAAG,MAAM,EAC/B,MAAM,GAAE,KAAK,GAAG,OAAO,GAAG,OAAe,GACxC,YAAY,CAoBd;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAQ3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,CAelG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAKhE;AAMD,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAaxF"}
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ /**
3
+ * Utilitaires pour la détection et conversion de formats
4
+ *
5
+ * Gère la rétrocompatibilité entre:
6
+ * - Ancien format: JSON Lexical brut (string)
7
+ * - Nouveau format: PageDocument avec sections
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.detectFormat = detectFormat;
11
+ exports.isPageDocument = isPageDocument;
12
+ exports.isLexicalState = isLexicalState;
13
+ exports.lexicalToPageDocument = lexicalToPageDocument;
14
+ exports.pageDocumentToLexical = pageDocumentToLexical;
15
+ exports.ensurePageDocument = ensurePageDocument;
16
+ exports.isSimpleDocument = isSimpleDocument;
17
+ exports.prepareForSave = prepareForSave;
18
+ const page_1 = require("../types/page");
19
+ // ============================================
20
+ // Détection du format
21
+ // ============================================
22
+ /**
23
+ * Détecte le format du contenu
24
+ *
25
+ * @param content - Le contenu à analyser (string JSON ou objet)
26
+ * @returns Le type de format détecté et les données parsées
27
+ */
28
+ function detectFormat(content) {
29
+ // Cas vide
30
+ if (!content) {
31
+ return { format: 'empty', data: null };
32
+ }
33
+ // Si c'est déjà un objet
34
+ if (typeof content === 'object') {
35
+ if (isPageDocument(content)) {
36
+ return { format: 'page-document', data: content };
37
+ }
38
+ // Objet mais pas un PageDocument - probablement du Lexical parsé
39
+ return { format: 'lexical', data: JSON.stringify(content) };
40
+ }
41
+ // C'est une string - essayer de parser
42
+ if (typeof content === 'string') {
43
+ // String vide
44
+ if (!content.trim()) {
45
+ return { format: 'empty', data: null };
46
+ }
47
+ try {
48
+ const parsed = JSON.parse(content);
49
+ // Vérifier si c'est un PageDocument
50
+ if (isPageDocument(parsed)) {
51
+ return { format: 'page-document', data: parsed };
52
+ }
53
+ // Vérifier si c'est du Lexical (a un "root" avec "children")
54
+ if (isLexicalState(parsed)) {
55
+ return { format: 'lexical', data: content };
56
+ }
57
+ // JSON valide mais format inconnu
58
+ return { format: 'unknown', data: content };
59
+ }
60
+ catch {
61
+ // Pas du JSON - texte brut, on le traite comme vide ou texte simple
62
+ return { format: 'unknown', data: content };
63
+ }
64
+ }
65
+ return { format: 'unknown', data: null };
66
+ }
67
+ /**
68
+ * Vérifie si un objet est un PageDocument valide
69
+ */
70
+ function isPageDocument(obj) {
71
+ if (!obj || typeof obj !== 'object')
72
+ return false;
73
+ const doc = obj;
74
+ // Doit avoir un id et un format
75
+ if (typeof doc.id !== 'string')
76
+ return false;
77
+ if (!['web', 'print', 'video'].includes(doc.format))
78
+ return false;
79
+ // Doit avoir un array sections
80
+ if (!Array.isArray(doc.sections))
81
+ return false;
82
+ return true;
83
+ }
84
+ /**
85
+ * Vérifie si un objet est un état Lexical valide
86
+ */
87
+ function isLexicalState(obj) {
88
+ if (!obj || typeof obj !== 'object')
89
+ return false;
90
+ const state = obj;
91
+ // Lexical state a toujours un "root" avec des "children"
92
+ if (!state.root || typeof state.root !== 'object')
93
+ return false;
94
+ const root = state.root;
95
+ if (!Array.isArray(root.children))
96
+ return false;
97
+ return true;
98
+ }
99
+ // ============================================
100
+ // Conversion de format
101
+ // ============================================
102
+ /**
103
+ * Convertit du contenu Lexical brut en PageDocument
104
+ * Crée une page avec une seule section "text-only" contenant l'éditeur
105
+ *
106
+ * @param lexicalContent - Le JSON Lexical (string ou objet)
107
+ * @param format - Le format de page souhaité (défaut: 'web')
108
+ * @returns Un PageDocument avec le contenu Lexical dans une section
109
+ */
110
+ function lexicalToPageDocument(lexicalContent, format = 'web') {
111
+ const lexicalString = typeof lexicalContent === 'string'
112
+ ? lexicalContent
113
+ : JSON.stringify(lexicalContent);
114
+ const section = {
115
+ id: (0, page_1.generateId)(),
116
+ layoutType: 'text-only',
117
+ content: {
118
+ lexicalState: lexicalString,
119
+ },
120
+ };
121
+ return {
122
+ id: (0, page_1.generateId)(),
123
+ format,
124
+ sections: [section],
125
+ createdAt: new Date().toISOString(),
126
+ updatedAt: new Date().toISOString(),
127
+ };
128
+ }
129
+ /**
130
+ * Extrait le contenu Lexical d'un PageDocument
131
+ * Si le document a une seule section "text-only", retourne le Lexical brut
132
+ * Sinon, retourne null (le document utilise le nouveau format)
133
+ *
134
+ * @param document - Le PageDocument à analyser
135
+ * @returns Le JSON Lexical si applicable, sinon null
136
+ */
137
+ function pageDocumentToLexical(document) {
138
+ // Si le document a exactement une section de type "text-only"
139
+ if (document.sections.length === 1 && document.sections[0].layoutType === 'text-only') {
140
+ const content = document.sections[0].content;
141
+ return content.lexicalState || null;
142
+ }
143
+ return null;
144
+ }
145
+ /**
146
+ * Convertit automatiquement le contenu vers PageDocument si nécessaire
147
+ *
148
+ * @param content - Le contenu (peut être Lexical ou PageDocument)
149
+ * @returns Un PageDocument valide
150
+ */
151
+ function ensurePageDocument(content) {
152
+ const detection = detectFormat(content);
153
+ switch (detection.format) {
154
+ case 'page-document':
155
+ return detection.data;
156
+ case 'lexical':
157
+ return lexicalToPageDocument(detection.data);
158
+ case 'empty':
159
+ case 'unknown':
160
+ default:
161
+ return (0, page_1.createEmptyPage)('web');
162
+ }
163
+ }
164
+ /**
165
+ * Vérifie si un PageDocument est "simple" (une seule section text-only)
166
+ * Utile pour décider comment sauvegarder
167
+ */
168
+ function isSimpleDocument(document) {
169
+ return (document.sections.length === 1 &&
170
+ document.sections[0].layoutType === 'text-only');
171
+ }
172
+ /**
173
+ * Prépare le contenu pour la sauvegarde
174
+ *
175
+ * @param document - Le PageDocument à sauvegarder
176
+ * @param options - Options de sauvegarde
177
+ * @returns String JSON à sauvegarder
178
+ */
179
+ function prepareForSave(document, options = {}) {
180
+ const { preferLegacyFormat = false } = options;
181
+ // Si on préfère le format legacy et que c'est possible
182
+ if (preferLegacyFormat && isSimpleDocument(document)) {
183
+ const lexical = pageDocumentToLexical(document);
184
+ if (lexical) {
185
+ return lexical;
186
+ }
187
+ }
188
+ // Sinon, sauvegarder comme PageDocument
189
+ return JSON.stringify(document);
190
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Re-export all utilities
3
+ */
4
+ export * from './format';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,UAAU,CAAA"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * Re-export all utilities
19
+ */
20
+ __exportStar(require("./format"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qwanyx/ai-editor",
3
- "version": "1.3.13",
3
+ "version": "1.4.0",
4
4
  "description": "AI-powered WYSIWYG rich text editor",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",