magic-editor-x 1.0.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 (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +890 -0
  3. package/dist/_chunks/App-B1FgOsWa.mjs +2143 -0
  4. package/dist/_chunks/App-mtrlABtd.js +2146 -0
  5. package/dist/_chunks/LicensePage-BnyWSrWs.js +375 -0
  6. package/dist/_chunks/LicensePage-CWH-AFR-.mjs +373 -0
  7. package/dist/_chunks/LiveCollaborationPanel-DbDHwr2C.js +222 -0
  8. package/dist/_chunks/LiveCollaborationPanel-ryjcDAA7.mjs +220 -0
  9. package/dist/_chunks/Settings-Bk9bxJTy.js +440 -0
  10. package/dist/_chunks/Settings-D-V2MLVm.mjs +438 -0
  11. package/dist/_chunks/de-CSrHZWEb.mjs +295 -0
  12. package/dist/_chunks/de-CzSo1oD2.js +295 -0
  13. package/dist/_chunks/en-DuQun2v4.mjs +295 -0
  14. package/dist/_chunks/en-DxIkVPUh.js +295 -0
  15. package/dist/_chunks/es-DAQ_97zx.js +273 -0
  16. package/dist/_chunks/es-DEB0CA8S.mjs +273 -0
  17. package/dist/_chunks/fr-Bqkhvdx2.mjs +273 -0
  18. package/dist/_chunks/fr-ChPabvNP.js +273 -0
  19. package/dist/_chunks/getTranslation-C4uWR0DB.mjs +50985 -0
  20. package/dist/_chunks/getTranslation-D35vbDap.js +51001 -0
  21. package/dist/_chunks/index-B5MzUyo0.mjs +2541 -0
  22. package/dist/_chunks/index-BRVqbnOb.mjs +4450 -0
  23. package/dist/_chunks/index-BiLy_f7C.js +2540 -0
  24. package/dist/_chunks/index-CQx7-dFP.js +4472 -0
  25. package/dist/_chunks/pt-BMoYltav.mjs +273 -0
  26. package/dist/_chunks/pt-Cm74LpyZ.js +273 -0
  27. package/dist/_chunks/tools-CjnQJ9w2.mjs +2155 -0
  28. package/dist/_chunks/tools-DNt2tioN.js +2186 -0
  29. package/dist/admin/index.js +3 -0
  30. package/dist/admin/index.mjs +4 -0
  31. package/dist/server/index.js +2554 -0
  32. package/dist/server/index.mjs +2544 -0
  33. package/dist/style.css +164 -0
  34. package/package.json +122 -0
  35. package/pics/collab-magiceditorX.png +0 -0
  36. package/pics/editorX.png +0 -0
  37. package/pics/liveCollabwidget1.png +0 -0
@@ -0,0 +1,2143 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from "react";
3
+ import { useNavigate, Routes, Route } from "react-router-dom";
4
+ import { useFetchClient, useNotification, Page } from "@strapi/strapi/admin";
5
+ import styled, { css, keyframes } from "styled-components";
6
+ import { HashtagIcon, DocumentTextIcon, ListBulletIcon, CheckIcon, ChatBubbleBottomCenterTextIcon, CodeBracketIcon, PhotoIcon, TableCellsIcon, LinkIcon, ExclamationTriangleIcon, PaperClipIcon, BellAlertIcon, SparklesIcon, BeakerIcon, PlayCircleIcon, ArrowPathIcon, EyeIcon, DocumentDuplicateIcon, ChevronRightIcon, CubeTransparentIcon, Cog6ToothIcon, UserGroupIcon, BookOpenIcon, CommandLineIcon, UserPlusIcon, TrashIcon, CheckCircleIcon, XMarkIcon, KeyIcon } from "@heroicons/react/24/outline";
7
+ import EditorJS from "@editorjs/editorjs";
8
+ import { u as useIntl, g as getTranslation, L as Loader, B as Box, T as Typography, a as Flex, b as TextInput, c as Button$2 } from "./getTranslation-C4uWR0DB.mjs";
9
+ import { g as getTools } from "./tools-CjnQJ9w2.mjs";
10
+ import { P as PLUGIN_ID } from "./index-B5MzUyo0.mjs";
11
+ import LicensePage from "./LicensePage-CWH-AFR-.mjs";
12
+ const fadeInUp = keyframes`
13
+ from { opacity: 0; transform: translateY(20px); }
14
+ to { opacity: 1; transform: translateY(0); }
15
+ `;
16
+ const pulse = keyframes`
17
+ 0%, 100% { opacity: 1; transform: scale(1); }
18
+ 50% { opacity: 0.8; transform: scale(1.05); }
19
+ `;
20
+ keyframes`
21
+ 0% { background-position: -200% 0; }
22
+ 100% { background-position: 200% 0; }
23
+ `;
24
+ const spin = keyframes`
25
+ from { transform: rotate(0deg); }
26
+ to { transform: rotate(360deg); }
27
+ `;
28
+ const PageWrapper = styled.div`
29
+ min-height: 100vh;
30
+ background: ${(props) => props.theme.colors.neutral100};
31
+ `;
32
+ const Container$1 = styled.div`
33
+ max-width: 1400px;
34
+ margin: 0 auto;
35
+ padding: 32px;
36
+ `;
37
+ const Header$1 = styled.header`
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: space-between;
41
+ margin-bottom: 32px;
42
+ padding-bottom: 24px;
43
+ border-bottom: 1px solid ${(props) => props.theme.colors.neutral200};
44
+ `;
45
+ const HeaderLeft = styled.div`
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 16px;
49
+ `;
50
+ const Logo = styled.div`
51
+ width: 48px;
52
+ height: 48px;
53
+ background: linear-gradient(135deg, #7C3AED 0%, #6366f1 100%);
54
+ border-radius: 14px;
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ box-shadow: 0 8px 24px rgba(124, 58, 237, 0.3);
59
+
60
+ svg {
61
+ width: 26px;
62
+ height: 26px;
63
+ color: white;
64
+ }
65
+ `;
66
+ const HeaderTitle = styled.div`
67
+ h1 {
68
+ font-size: 24px;
69
+ font-weight: 700;
70
+ color: ${(props) => props.theme.colors.neutral800};
71
+ margin: 0 0 4px 0;
72
+ }
73
+
74
+ p {
75
+ font-size: 14px;
76
+ color: ${(props) => props.theme.colors.neutral600};
77
+ margin: 0;
78
+ }
79
+ `;
80
+ const HeaderRight = styled.div`
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 12px;
84
+ `;
85
+ const StatusBadge = styled.div`
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 8px;
89
+ padding: 8px 16px;
90
+ background: ${(props) => props.$active ? "rgba(34, 197, 94, 0.1)" : "rgba(100, 116, 139, 0.1)"};
91
+ border: 1px solid ${(props) => props.$active ? "rgba(34, 197, 94, 0.2)" : "rgba(100, 116, 139, 0.2)"};
92
+ border-radius: 100px;
93
+ font-size: 13px;
94
+ font-weight: 500;
95
+ color: ${(props) => props.$active ? "#22c55e" : "#64748b"};
96
+
97
+ &::before {
98
+ content: '';
99
+ width: 8px;
100
+ height: 8px;
101
+ background: ${(props) => props.$active ? "#22c55e" : "#64748b"};
102
+ border-radius: 50%;
103
+ animation: ${(props) => props.$active ? pulse : "none"} 2s ease-in-out infinite;
104
+ }
105
+ `;
106
+ const Grid = styled.div`
107
+ display: grid;
108
+ grid-template-columns: 1fr 380px;
109
+ gap: 24px;
110
+
111
+ @media (max-width: 1100px) {
112
+ grid-template-columns: 1fr;
113
+ }
114
+ `;
115
+ const MainArea = styled.div`
116
+ display: flex;
117
+ flex-direction: column;
118
+ gap: 24px;
119
+ `;
120
+ const Sidebar = styled.aside`
121
+ display: flex;
122
+ flex-direction: column;
123
+ gap: 24px;
124
+ `;
125
+ const Card$1 = styled.div`
126
+ background: ${(props) => props.theme.colors.neutral0};
127
+ border: 1px solid ${(props) => props.theme.colors.neutral200};
128
+ border-radius: 16px;
129
+ overflow: hidden;
130
+ animation: ${fadeInUp} 0.5s ease ${(props) => props.$delay || 0}s both;
131
+ `;
132
+ const CardHeader$1 = styled.div`
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: space-between;
136
+ padding: 20px 24px;
137
+ border-bottom: 1px solid ${(props) => props.theme.colors.neutral200};
138
+ background: ${(props) => props.theme.colors.neutral100};
139
+ `;
140
+ const CardTitle$1 = styled.h2`
141
+ display: flex;
142
+ align-items: center;
143
+ gap: 10px;
144
+ font-size: 16px;
145
+ font-weight: 600;
146
+ color: ${(props) => props.theme.colors.neutral800};
147
+ margin: 0;
148
+
149
+ svg {
150
+ width: 20px;
151
+ height: 20px;
152
+ color: #7C3AED;
153
+ }
154
+ `;
155
+ const CardContent = styled.div`
156
+ padding: ${(props) => props.$noPadding ? "0" : "24px"};
157
+ `;
158
+ const CardActions = styled.div`
159
+ display: flex;
160
+ gap: 8px;
161
+ `;
162
+ const IconButton = styled.button`
163
+ width: 36px;
164
+ height: 36px;
165
+ border: 1px solid ${(props) => props.theme.colors.neutral200};
166
+ border-radius: 10px;
167
+ background: ${(props) => props.theme.colors.neutral0};
168
+ color: ${(props) => props.theme.colors.neutral600};
169
+ display: flex;
170
+ align-items: center;
171
+ justify-content: center;
172
+ cursor: pointer;
173
+ transition: all 0.15s ease;
174
+
175
+ svg {
176
+ width: 18px;
177
+ height: 18px;
178
+ }
179
+
180
+ &:hover {
181
+ background: ${(props) => props.theme.colors.neutral100};
182
+ border-color: #7C3AED;
183
+ color: #7C3AED;
184
+ }
185
+
186
+ ${(props) => props.$spinning && css`
187
+ svg {
188
+ animation: ${spin} 1s linear infinite;
189
+ }
190
+ `}
191
+ `;
192
+ const Button$1 = styled.button`
193
+ display: inline-flex;
194
+ align-items: center;
195
+ gap: 8px;
196
+ padding: 10px 20px;
197
+ background: ${(props) => props.$primary ? "linear-gradient(135deg, #7C3AED 0%, #6366f1 100%)" : props.theme.colors.neutral0};
198
+ border: 1px solid ${(props) => props.$primary ? "transparent" : props.theme.colors.neutral200};
199
+ border-radius: 10px;
200
+ font-size: 14px;
201
+ font-weight: 600;
202
+ color: ${(props) => props.$primary ? "white" : props.theme.colors.neutral800};
203
+ cursor: pointer;
204
+ transition: all 0.2s ease;
205
+
206
+ svg {
207
+ width: 18px;
208
+ height: 18px;
209
+ }
210
+
211
+ &:hover {
212
+ transform: translateY(-2px);
213
+ box-shadow: ${(props) => props.$primary ? "0 8px 24px rgba(124, 58, 237, 0.3)" : "0 4px 12px rgba(0, 0, 0, 0.1)"};
214
+ }
215
+
216
+ &:disabled {
217
+ opacity: 0.6;
218
+ cursor: not-allowed;
219
+ transform: none;
220
+ }
221
+ `;
222
+ const PlaygroundWrapper = styled.div`
223
+ min-height: 400px;
224
+ border: 2px dashed ${(props) => props.theme.colors.neutral300};
225
+ border-radius: 12px;
226
+ margin: 16px;
227
+ position: relative;
228
+ transition: all 0.2s ease;
229
+
230
+ &:focus-within {
231
+ border-color: #7C3AED;
232
+ border-style: solid;
233
+ }
234
+ `;
235
+ const PlaygroundEditor = styled.div`
236
+ padding: 24px;
237
+ min-height: 350px;
238
+
239
+ .codex-editor__redactor {
240
+ padding-bottom: 60px !important;
241
+ }
242
+ `;
243
+ const PlaygroundEmpty = styled.div`
244
+ position: absolute;
245
+ top: 50%;
246
+ left: 50%;
247
+ transform: translate(-50%, -50%);
248
+ text-align: center;
249
+ color: ${(props) => props.theme.colors.neutral500};
250
+ pointer-events: none;
251
+
252
+ svg {
253
+ width: 48px;
254
+ height: 48px;
255
+ margin-bottom: 12px;
256
+ opacity: 0.5;
257
+ }
258
+
259
+ p {
260
+ font-size: 15px;
261
+ margin: 0;
262
+ }
263
+ `;
264
+ const OutputPreview = styled.div`
265
+ background: #1e293b;
266
+ border-radius: 12px;
267
+ margin: 16px;
268
+ overflow: hidden;
269
+ `;
270
+ const OutputHeader = styled.div`
271
+ display: flex;
272
+ align-items: center;
273
+ justify-content: space-between;
274
+ padding: 12px 16px;
275
+ background: #0f172a;
276
+ border-bottom: 1px solid #334155;
277
+ `;
278
+ const OutputTitle = styled.span`
279
+ font-size: 12px;
280
+ font-weight: 600;
281
+ color: #94a3b8;
282
+ text-transform: uppercase;
283
+ letter-spacing: 0.5px;
284
+ `;
285
+ const OutputContent = styled.pre`
286
+ padding: 16px;
287
+ margin: 0;
288
+ font-family: 'JetBrains Mono', 'SF Mono', Monaco, monospace;
289
+ font-size: 12px;
290
+ color: #e2e8f0;
291
+ overflow-x: auto;
292
+ max-height: 300px;
293
+
294
+ .key { color: #7dd3fc; }
295
+ .string { color: #86efac; }
296
+ .number { color: #fcd34d; }
297
+ .boolean { color: #f472b6; }
298
+ .null { color: #94a3b8; }
299
+ `;
300
+ const ToolGrid = styled.div`
301
+ display: grid;
302
+ grid-template-columns: repeat(2, 1fr);
303
+ gap: 8px;
304
+ padding: 16px;
305
+
306
+ @media (max-width: 480px) {
307
+ grid-template-columns: 1fr;
308
+ }
309
+ `;
310
+ const ToolItem = styled.div`
311
+ display: flex;
312
+ align-items: center;
313
+ gap: 10px;
314
+ padding: 12px;
315
+ background: ${(props) => props.$active ? "rgba(124, 58, 237, 0.08)" : props.theme.colors.neutral100};
316
+ border: 1px solid ${(props) => props.$active ? "rgba(124, 58, 237, 0.2)" : "transparent"};
317
+ border-radius: 10px;
318
+ cursor: pointer;
319
+ transition: all 0.15s ease;
320
+
321
+ &:hover {
322
+ background: rgba(124, 58, 237, 0.05);
323
+ }
324
+ `;
325
+ const ToolIcon = styled.div`
326
+ width: 32px;
327
+ height: 32px;
328
+ background: ${(props) => props.$color || "linear-gradient(135deg, #7C3AED 0%, #6366f1 100%)"};
329
+ border-radius: 8px;
330
+ display: flex;
331
+ align-items: center;
332
+ justify-content: center;
333
+
334
+ svg {
335
+ width: 16px;
336
+ height: 16px;
337
+ color: white;
338
+ }
339
+ `;
340
+ const ToolInfo = styled.div`
341
+ flex: 1;
342
+ min-width: 0;
343
+
344
+ h4 {
345
+ font-size: 13px;
346
+ font-weight: 600;
347
+ color: ${(props) => props.theme.colors.neutral800};
348
+ margin: 0 0 2px 0;
349
+ }
350
+
351
+ p {
352
+ font-size: 11px;
353
+ color: ${(props) => props.theme.colors.neutral600};
354
+ margin: 0;
355
+ white-space: nowrap;
356
+ overflow: hidden;
357
+ text-overflow: ellipsis;
358
+ }
359
+ `;
360
+ const ShortcutList = styled.div`
361
+ display: flex;
362
+ flex-direction: column;
363
+ gap: 4px;
364
+ padding: 16px;
365
+ `;
366
+ const ShortcutItem = styled.div`
367
+ display: flex;
368
+ align-items: center;
369
+ justify-content: space-between;
370
+ padding: 10px 12px;
371
+ background: ${(props) => props.theme.colors.neutral100};
372
+ border-radius: 8px;
373
+ `;
374
+ const ShortcutLabel = styled.span`
375
+ font-size: 13px;
376
+ color: ${(props) => props.theme.colors.neutral800};
377
+ `;
378
+ const ShortcutKeys = styled.div`
379
+ display: flex;
380
+ gap: 4px;
381
+ `;
382
+ const Kbd = styled.kbd`
383
+ display: inline-flex;
384
+ align-items: center;
385
+ justify-content: center;
386
+ min-width: 24px;
387
+ height: 24px;
388
+ padding: 0 8px;
389
+ background: ${(props) => props.theme.colors.neutral0};
390
+ border: 1px solid ${(props) => props.theme.colors.neutral200};
391
+ border-radius: 6px;
392
+ font-family: 'SF Mono', Monaco, monospace;
393
+ font-size: 11px;
394
+ font-weight: 600;
395
+ color: ${(props) => props.theme.colors.neutral600};
396
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
397
+ `;
398
+ const StatsGrid = styled.div`
399
+ display: grid;
400
+ grid-template-columns: repeat(2, 1fr);
401
+ gap: 12px;
402
+ padding: 16px;
403
+ `;
404
+ const StatCard = styled.div`
405
+ padding: 16px;
406
+ background: linear-gradient(135deg, ${(props) => props.$bg || "rgba(124, 58, 237, 0.05)"} 0%, transparent 100%);
407
+ border-radius: 12px;
408
+ text-align: center;
409
+ `;
410
+ const StatNumber = styled.div`
411
+ font-size: 28px;
412
+ font-weight: 800;
413
+ color: ${(props) => props.$color || "#7C3AED"};
414
+ margin-bottom: 4px;
415
+ `;
416
+ const StatLabel = styled.div`
417
+ font-size: 12px;
418
+ color: #64748b;
419
+ font-weight: 500;
420
+ `;
421
+ const TabsContainer = styled.div`
422
+ display: flex;
423
+ gap: 4px;
424
+ padding: 4px;
425
+ background: ${(props) => props.theme.colors.neutral150};
426
+ border-radius: 10px;
427
+ `;
428
+ const Tab = styled.button`
429
+ flex: 1;
430
+ padding: 8px 16px;
431
+ background: ${(props) => props.$active ? props.theme.colors.neutral0 : "transparent"};
432
+ border: none;
433
+ border-radius: 8px;
434
+ font-size: 13px;
435
+ font-weight: 500;
436
+ color: ${(props) => props.$active ? props.theme.colors.neutral800 : props.theme.colors.neutral600};
437
+ cursor: pointer;
438
+ transition: all 0.15s ease;
439
+ box-shadow: ${(props) => props.$active ? "0 1px 3px rgba(0, 0, 0, 0.1)" : "none"};
440
+
441
+ &:hover {
442
+ color: ${(props) => props.theme.colors.neutral800};
443
+ }
444
+ `;
445
+ const QuickLinksGrid = styled.div`
446
+ display: flex;
447
+ flex-direction: column;
448
+ gap: 8px;
449
+ padding: 16px;
450
+ `;
451
+ const QuickLinkItem = styled.button`
452
+ display: flex;
453
+ align-items: center;
454
+ gap: 12px;
455
+ padding: 14px 16px;
456
+ background: ${(props) => props.$active ? "rgba(124, 58, 237, 0.08)" : props.theme.colors.neutral100};
457
+ border: 1px solid ${(props) => props.$active ? "rgba(124, 58, 237, 0.2)" : "transparent"};
458
+ border-radius: 12px;
459
+ cursor: pointer;
460
+ transition: all 0.2s ease;
461
+ text-align: left;
462
+ width: 100%;
463
+
464
+ &:hover {
465
+ background: rgba(124, 58, 237, 0.08);
466
+ border-color: rgba(124, 58, 237, 0.2);
467
+ transform: translateX(4px);
468
+ }
469
+ `;
470
+ const QuickLinkIcon = styled.div`
471
+ width: 40px;
472
+ height: 40px;
473
+ background: ${(props) => props.$color || "linear-gradient(135deg, #7C3AED 0%, #6366f1 100%)"};
474
+ border-radius: 10px;
475
+ display: flex;
476
+ align-items: center;
477
+ justify-content: center;
478
+ flex-shrink: 0;
479
+
480
+ svg {
481
+ width: 20px;
482
+ height: 20px;
483
+ color: white;
484
+ }
485
+ `;
486
+ const QuickLinkInfo = styled.div`
487
+ flex: 1;
488
+ min-width: 0;
489
+
490
+ h4 {
491
+ font-size: 14px;
492
+ font-weight: 600;
493
+ color: ${(props) => props.theme.colors.neutral800};
494
+ margin: 0 0 2px 0;
495
+ }
496
+
497
+ p {
498
+ font-size: 12px;
499
+ color: ${(props) => props.theme.colors.neutral600};
500
+ margin: 0;
501
+ }
502
+ `;
503
+ const QuickLinkArrow = styled.div`
504
+ color: ${(props) => props.theme.colors.neutral500};
505
+
506
+ svg {
507
+ width: 16px;
508
+ height: 16px;
509
+ }
510
+ `;
511
+ const HomePage = () => {
512
+ const navigate = useNavigate();
513
+ const { formatMessage } = useIntl();
514
+ const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
515
+ const [activeTab, setActiveTab] = useState("playground");
516
+ const [editorData, setEditorData] = useState(null);
517
+ const [isLoading, setIsLoading] = useState(false);
518
+ const [hasContent, setHasContent] = useState(false);
519
+ const editorRef = useRef(null);
520
+ const editorInstanceRef = useRef(null);
521
+ const toolsData = [
522
+ { name: t("tools.header", "Header"), desc: t("tools.header.desc", "H1-H6 Headings"), icon: HashtagIcon, color: "linear-gradient(135deg, #7C3AED, #6366f1)" },
523
+ { name: t("tools.paragraph", "Paragraph"), desc: t("tools.paragraph.desc", "Text paragraphs"), icon: DocumentTextIcon, color: "linear-gradient(135deg, #334155, #475569)" },
524
+ { name: t("tools.list", "List"), desc: t("tools.list.desc", "Nested lists"), icon: ListBulletIcon, color: "linear-gradient(135deg, #14b8a6, #2dd4bf)" },
525
+ { name: t("tools.checklist", "Checklist"), desc: t("tools.checklist.desc", "Interactive checkboxes"), icon: CheckIcon, color: "linear-gradient(135deg, #22c55e, #4ade80)" },
526
+ { name: t("tools.quote", "Quote"), desc: t("tools.quote.desc", "Quotes with author"), icon: ChatBubbleBottomCenterTextIcon, color: "linear-gradient(135deg, #f59e0b, #fbbf24)" },
527
+ { name: t("tools.code", "Code"), desc: t("tools.code.desc", "Code blocks"), icon: CodeBracketIcon, color: "linear-gradient(135deg, #06b6d4, #22d3ee)" },
528
+ { name: t("tools.image", "Image"), desc: t("tools.image.desc", "Upload images"), icon: PhotoIcon, color: "linear-gradient(135deg, #ec4899, #f472b6)" },
529
+ { name: t("tools.table", "Table"), desc: t("tools.table.desc", "Create tables"), icon: TableCellsIcon, color: "linear-gradient(135deg, #8b5cf6, #a78bfa)" },
530
+ { name: t("tools.link", "Link"), desc: t("tools.link.desc", "Link preview"), icon: LinkIcon, color: "linear-gradient(135deg, #3b82f6, #60a5fa)" },
531
+ { name: t("tools.warning", "Warning"), desc: t("tools.warning.desc", "Warning notices"), icon: ExclamationTriangleIcon, color: "linear-gradient(135deg, #ef4444, #f87171)" },
532
+ { name: t("tools.attaches", "Attaches"), desc: t("tools.attaches.desc", "File attachments"), icon: PaperClipIcon, color: "linear-gradient(135deg, #64748b, #94a3b8)" },
533
+ { name: t("tools.alert", "Alert"), desc: t("tools.alert.desc", "Colored alerts"), icon: BellAlertIcon, color: "linear-gradient(135deg, #f97316, #fb923c)" }
534
+ ];
535
+ const shortcuts = [
536
+ { keys: ["⌘", "B"], label: t("shortcuts.bold", "Bold") },
537
+ { keys: ["⌘", "I"], label: t("shortcuts.italic", "Italic") },
538
+ { keys: ["⌘", "U"], label: t("shortcuts.underline", "Underline") },
539
+ { keys: ["⌘", "⇧", "H"], label: t("shortcuts.heading", "Heading") },
540
+ { keys: ["⌘", "⇧", "L"], label: t("shortcuts.list", "List") },
541
+ { keys: ["⌘", "⇧", "M"], label: t("shortcuts.highlight", "Highlight") },
542
+ { keys: ["Tab"], label: t("shortcuts.blockMenu", "Block Menu") },
543
+ { keys: ["⌘", "Z"], label: t("shortcuts.undo", "Undo") }
544
+ ];
545
+ useEffect(() => {
546
+ if (activeTab === "playground" && editorRef.current && !editorInstanceRef.current) {
547
+ const tools = getTools({
548
+ mediaLibToggleFunc: () => {
549
+ },
550
+ pluginId: PLUGIN_ID
551
+ });
552
+ const playgroundTools = { ...tools };
553
+ delete playgroundTools.image;
554
+ delete playgroundTools.attaches;
555
+ delete playgroundTools.linkTool;
556
+ delete playgroundTools.personality;
557
+ delete playgroundTools.mediaLib;
558
+ editorInstanceRef.current = new EditorJS({
559
+ holder: editorRef.current,
560
+ tools: playgroundTools,
561
+ placeholder: t("homepage.playground.placeholder", "Type / for block menu or start writing..."),
562
+ onChange: async () => {
563
+ try {
564
+ const data = await editorInstanceRef.current.save();
565
+ setEditorData(data);
566
+ setHasContent(data.blocks && data.blocks.length > 0);
567
+ } catch (e) {
568
+ console.warn("Could not save:", e);
569
+ }
570
+ }
571
+ });
572
+ }
573
+ return () => {
574
+ if (editorInstanceRef.current && editorInstanceRef.current.destroy) {
575
+ editorInstanceRef.current.destroy();
576
+ editorInstanceRef.current = null;
577
+ }
578
+ };
579
+ }, [activeTab]);
580
+ const clearPlayground = async () => {
581
+ if (editorInstanceRef.current) {
582
+ await editorInstanceRef.current.clear();
583
+ setEditorData(null);
584
+ setHasContent(false);
585
+ }
586
+ };
587
+ const copyJSON = () => {
588
+ if (editorData) {
589
+ navigator.clipboard.writeText(JSON.stringify(editorData, null, 2));
590
+ }
591
+ };
592
+ const formatJSON = (obj) => {
593
+ if (!obj) return "";
594
+ const json = JSON.stringify(obj, null, 2);
595
+ return json.replace(/"([^"]+)":/g, '<span class="key">"$1"</span>:').replace(/: "([^"]*)"/g, ': <span class="string">"$1"</span>').replace(/: (\d+)/g, ': <span class="number">$1</span>').replace(/: (true|false)/g, ': <span class="boolean">$1</span>').replace(/: null/g, ': <span class="null">null</span>');
596
+ };
597
+ return /* @__PURE__ */ jsx(PageWrapper, { children: /* @__PURE__ */ jsxs(Container$1, { children: [
598
+ /* @__PURE__ */ jsxs(Header$1, { children: [
599
+ /* @__PURE__ */ jsxs(HeaderLeft, { children: [
600
+ /* @__PURE__ */ jsx(Logo, { children: /* @__PURE__ */ jsx(SparklesIcon, {}) }),
601
+ /* @__PURE__ */ jsxs(HeaderTitle, { children: [
602
+ /* @__PURE__ */ jsx("h1", { children: t("homepage.title", "Magic Editor X") }),
603
+ /* @__PURE__ */ jsx("p", { children: t("homepage.subtitle", "Block Editor Dashboard for Strapi v5") })
604
+ ] })
605
+ ] }),
606
+ /* @__PURE__ */ jsx(HeaderRight, { children: /* @__PURE__ */ jsx(StatusBadge, { $active: true, children: t("homepage.status.ready", "Realtime Ready") }) })
607
+ ] }),
608
+ /* @__PURE__ */ jsxs(Grid, { children: [
609
+ /* @__PURE__ */ jsxs(MainArea, { children: [
610
+ /* @__PURE__ */ jsxs(Card$1, { $delay: 0.1, children: [
611
+ /* @__PURE__ */ jsxs(CardHeader$1, { children: [
612
+ /* @__PURE__ */ jsxs(CardTitle$1, { children: [
613
+ /* @__PURE__ */ jsx(BeakerIcon, {}),
614
+ t("homepage.playground", "Editor Playground")
615
+ ] }),
616
+ /* @__PURE__ */ jsx(CardActions, { children: /* @__PURE__ */ jsxs(TabsContainer, { children: [
617
+ /* @__PURE__ */ jsx(Tab, { $active: activeTab === "playground", onClick: () => setActiveTab("playground"), children: t("homepage.tabs.editor", "Editor") }),
618
+ /* @__PURE__ */ jsx(Tab, { $active: activeTab === "output", onClick: () => setActiveTab("output"), children: t("homepage.tabs.output", "JSON Output") })
619
+ ] }) })
620
+ ] }),
621
+ activeTab === "playground" ? /* @__PURE__ */ jsxs(CardContent, { $noPadding: true, children: [
622
+ /* @__PURE__ */ jsxs(PlaygroundWrapper, { children: [
623
+ /* @__PURE__ */ jsx(PlaygroundEditor, { ref: editorRef }),
624
+ !hasContent && /* @__PURE__ */ jsxs(PlaygroundEmpty, { children: [
625
+ /* @__PURE__ */ jsx(PlayCircleIcon, {}),
626
+ /* @__PURE__ */ jsx("p", { children: t("homepage.playground.empty", "Type here to try the editor") })
627
+ ] })
628
+ ] }),
629
+ /* @__PURE__ */ jsxs("div", { style: { padding: "0 16px 16px", display: "flex", gap: "8px" }, children: [
630
+ /* @__PURE__ */ jsxs(Button$1, { onClick: clearPlayground, children: [
631
+ /* @__PURE__ */ jsx(ArrowPathIcon, {}),
632
+ t("homepage.button.clear", "Clear")
633
+ ] }),
634
+ hasContent && /* @__PURE__ */ jsxs(Button$1, { $primary: true, onClick: () => setActiveTab("output"), children: [
635
+ /* @__PURE__ */ jsx(EyeIcon, {}),
636
+ t("homepage.button.showJson", "Show JSON")
637
+ ] })
638
+ ] })
639
+ ] }) : /* @__PURE__ */ jsxs(CardContent, { $noPadding: true, children: [
640
+ /* @__PURE__ */ jsxs(OutputPreview, { children: [
641
+ /* @__PURE__ */ jsxs(OutputHeader, { children: [
642
+ /* @__PURE__ */ jsx(OutputTitle, { children: t("homepage.output.title", "Editor.js JSON Output") }),
643
+ /* @__PURE__ */ jsx(IconButton, { onClick: copyJSON, title: t("homepage.button.copyJson", "Copy JSON"), children: /* @__PURE__ */ jsx(DocumentDuplicateIcon, {}) })
644
+ ] }),
645
+ /* @__PURE__ */ jsx(
646
+ OutputContent,
647
+ {
648
+ dangerouslySetInnerHTML: {
649
+ __html: editorData ? formatJSON(editorData) : `<span class="null">${t("homepage.output.empty", "// No content - create blocks in the editor")}</span>`
650
+ }
651
+ }
652
+ )
653
+ ] }),
654
+ /* @__PURE__ */ jsx("div", { style: { padding: "0 16px 16px" }, children: /* @__PURE__ */ jsxs(Button$1, { onClick: () => setActiveTab("playground"), children: [
655
+ /* @__PURE__ */ jsx(ChevronRightIcon, { style: { transform: "rotate(180deg)" } }),
656
+ t("homepage.button.backToEditor", "Back to Editor")
657
+ ] }) })
658
+ ] })
659
+ ] }),
660
+ /* @__PURE__ */ jsxs(Card$1, { $delay: 0.2, children: [
661
+ /* @__PURE__ */ jsx(CardHeader$1, { children: /* @__PURE__ */ jsxs(CardTitle$1, { children: [
662
+ /* @__PURE__ */ jsx(CubeTransparentIcon, {}),
663
+ t("homepage.features.title", "Editor Features")
664
+ ] }) }),
665
+ /* @__PURE__ */ jsx(CardContent, { $noPadding: true, children: /* @__PURE__ */ jsxs(StatsGrid, { children: [
666
+ /* @__PURE__ */ jsxs(StatCard, { $bg: "rgba(124, 58, 237, 0.08)", children: [
667
+ /* @__PURE__ */ jsx(StatNumber, { $color: "#7C3AED", children: "21+" }),
668
+ /* @__PURE__ */ jsx(StatLabel, { children: t("homepage.stats.blockTools", "Block Tools") })
669
+ ] }),
670
+ /* @__PURE__ */ jsxs(StatCard, { $bg: "rgba(236, 72, 153, 0.08)", children: [
671
+ /* @__PURE__ */ jsx(StatNumber, { $color: "#ec4899", children: "6" }),
672
+ /* @__PURE__ */ jsx(StatLabel, { children: t("homepage.stats.inlineTools", "Inline Tools") })
673
+ ] }),
674
+ /* @__PURE__ */ jsxs(StatCard, { $bg: "rgba(34, 197, 94, 0.08)", children: [
675
+ /* @__PURE__ */ jsx(StatNumber, { $color: "#22c55e", children: "✓" }),
676
+ /* @__PURE__ */ jsx(StatLabel, { children: t("homepage.stats.realtimeCollab", "Realtime Collab") })
677
+ ] }),
678
+ /* @__PURE__ */ jsxs(StatCard, { $bg: "rgba(59, 130, 246, 0.08)", children: [
679
+ /* @__PURE__ */ jsx(StatNumber, { $color: "#3b82f6", children: "v5" }),
680
+ /* @__PURE__ */ jsx(StatLabel, { children: t("homepage.stats.strapiReady", "Strapi Ready") })
681
+ ] })
682
+ ] }) })
683
+ ] })
684
+ ] }),
685
+ /* @__PURE__ */ jsxs(Sidebar, { children: [
686
+ /* @__PURE__ */ jsxs(Card$1, { $delay: 0.25, children: [
687
+ /* @__PURE__ */ jsx(CardHeader$1, { children: /* @__PURE__ */ jsxs(CardTitle$1, { children: [
688
+ /* @__PURE__ */ jsx(Cog6ToothIcon, {}),
689
+ t("homepage.quickLinks.title", "Quick Access")
690
+ ] }) }),
691
+ /* @__PURE__ */ jsx(CardContent, { $noPadding: true, children: /* @__PURE__ */ jsxs(QuickLinksGrid, { children: [
692
+ /* @__PURE__ */ jsxs(QuickLinkItem, { onClick: () => navigate("collaboration"), children: [
693
+ /* @__PURE__ */ jsx(QuickLinkIcon, { $color: "linear-gradient(135deg, #7C3AED 0%, #6366f1 100%)", children: /* @__PURE__ */ jsx(UserGroupIcon, {}) }),
694
+ /* @__PURE__ */ jsxs(QuickLinkInfo, { children: [
695
+ /* @__PURE__ */ jsx("h4", { children: t("homepage.quickLinks.collaboration", "Collaboration") }),
696
+ /* @__PURE__ */ jsx("p", { children: t("homepage.quickLinks.collaboration.desc", "Manage users & permissions") })
697
+ ] }),
698
+ /* @__PURE__ */ jsx(QuickLinkArrow, { children: /* @__PURE__ */ jsx(ChevronRightIcon, {}) })
699
+ ] }),
700
+ /* @__PURE__ */ jsxs(QuickLinkItem, { onClick: () => window.open("https://editorjs.io/base-concepts/", "_blank"), children: [
701
+ /* @__PURE__ */ jsx(QuickLinkIcon, { $color: "linear-gradient(135deg, #3b82f6 0%, #60a5fa 100%)", children: /* @__PURE__ */ jsx(BookOpenIcon, {}) }),
702
+ /* @__PURE__ */ jsxs(QuickLinkInfo, { children: [
703
+ /* @__PURE__ */ jsx("h4", { children: t("homepage.quickLinks.docs", "Editor.js Docs") }),
704
+ /* @__PURE__ */ jsx("p", { children: t("homepage.quickLinks.docs.desc", "Official documentation") })
705
+ ] }),
706
+ /* @__PURE__ */ jsx(QuickLinkArrow, { children: /* @__PURE__ */ jsx(ChevronRightIcon, {}) })
707
+ ] })
708
+ ] }) })
709
+ ] }),
710
+ /* @__PURE__ */ jsxs(Card$1, { $delay: 0.3, children: [
711
+ /* @__PURE__ */ jsx(CardHeader$1, { children: /* @__PURE__ */ jsxs(CardTitle$1, { children: [
712
+ /* @__PURE__ */ jsx(BookOpenIcon, {}),
713
+ t("homepage.tools.title", "Available Tools")
714
+ ] }) }),
715
+ /* @__PURE__ */ jsx(CardContent, { $noPadding: true, children: /* @__PURE__ */ jsx(ToolGrid, { children: toolsData.map((tool, i) => /* @__PURE__ */ jsxs(ToolItem, { children: [
716
+ /* @__PURE__ */ jsx(ToolIcon, { $color: tool.color, children: /* @__PURE__ */ jsx(tool.icon, {}) }),
717
+ /* @__PURE__ */ jsxs(ToolInfo, { children: [
718
+ /* @__PURE__ */ jsx("h4", { children: tool.name }),
719
+ /* @__PURE__ */ jsx("p", { children: tool.desc })
720
+ ] })
721
+ ] }, i)) }) })
722
+ ] }),
723
+ /* @__PURE__ */ jsxs(Card$1, { $delay: 0.4, children: [
724
+ /* @__PURE__ */ jsx(CardHeader$1, { children: /* @__PURE__ */ jsxs(CardTitle$1, { children: [
725
+ /* @__PURE__ */ jsx(CommandLineIcon, {}),
726
+ t("homepage.shortcuts.title", "Keyboard Shortcuts")
727
+ ] }) }),
728
+ /* @__PURE__ */ jsx(CardContent, { $noPadding: true, children: /* @__PURE__ */ jsx(ShortcutList, { children: shortcuts.map((shortcut, i) => /* @__PURE__ */ jsxs(ShortcutItem, { children: [
729
+ /* @__PURE__ */ jsx(ShortcutLabel, { children: shortcut.label }),
730
+ /* @__PURE__ */ jsx(ShortcutKeys, { children: shortcut.keys.map((key, j) => /* @__PURE__ */ jsx(Kbd, { children: key }, j)) })
731
+ ] }, i)) }) })
732
+ ] })
733
+ ] })
734
+ ] })
735
+ ] }) });
736
+ };
737
+ const Container = styled.div`
738
+ padding: clamp(16px, 4vw, 40px);
739
+ max-width: 1400px;
740
+ margin: 0 auto;
741
+ min-height: 100vh;
742
+ box-sizing: border-box;
743
+ `;
744
+ const Header = styled.div`
745
+ margin-bottom: clamp(20px, 4vw, 32px);
746
+ `;
747
+ const Title = styled.h1`
748
+ font-size: clamp(22px, 4vw, 32px);
749
+ font-weight: 700;
750
+ color: ${(props) => props.theme.colors.neutral800};
751
+ margin: 0 0 8px 0;
752
+ display: flex;
753
+ align-items: center;
754
+ gap: 12px;
755
+ flex-wrap: wrap;
756
+
757
+ svg {
758
+ width: clamp(24px, 4vw, 32px);
759
+ height: clamp(24px, 4vw, 32px);
760
+ color: #7C3AED;
761
+ flex-shrink: 0;
762
+ }
763
+ `;
764
+ const Subtitle = styled.p`
765
+ font-size: clamp(13px, 2vw, 15px);
766
+ color: ${(props) => props.theme.colors.neutral600};
767
+ margin: 0;
768
+ `;
769
+ const Card = styled.div`
770
+ background: ${(props) => props.theme.colors.neutral0};
771
+ border: 1px solid ${(props) => props.theme.colors.neutral200};
772
+ border-radius: clamp(12px, 2vw, 16px);
773
+ padding: clamp(16px, 3vw, 24px);
774
+ margin-bottom: 24px;
775
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
776
+ overflow-x: auto;
777
+ `;
778
+ const CardHeader = styled.div`
779
+ display: flex;
780
+ align-items: center;
781
+ justify-content: space-between;
782
+ margin-bottom: 20px;
783
+ gap: 12px;
784
+ flex-wrap: wrap;
785
+
786
+ @media (max-width: 480px) {
787
+ flex-direction: column;
788
+ align-items: stretch;
789
+ }
790
+ `;
791
+ const CardTitle = styled.h2`
792
+ font-size: clamp(16px, 2.5vw, 18px);
793
+ font-weight: 600;
794
+ color: ${(props) => props.theme.colors.neutral800};
795
+ margin: 0;
796
+ `;
797
+ const Button = styled.button`
798
+ display: inline-flex;
799
+ align-items: center;
800
+ justify-content: center;
801
+ gap: 8px;
802
+ padding: clamp(8px, 1.5vw, 10px) clamp(14px, 2vw, 20px);
803
+ background: ${(props) => props.$danger ? "#ef4444" : props.$secondary ? props.theme.colors.neutral0 : "linear-gradient(135deg, #7C3AED 0%, #6d28d9 100%)"};
804
+ border: 1px solid ${(props) => props.$danger ? "#ef4444" : props.$secondary ? props.theme.colors.neutral200 : "transparent"};
805
+ border-radius: 10px;
806
+ color: ${(props) => props.$secondary ? props.theme.colors.neutral600 : "white"};
807
+ font-size: clamp(13px, 2vw, 14px);
808
+ font-weight: 500;
809
+ cursor: pointer;
810
+ transition: all 0.2s ease;
811
+ white-space: nowrap;
812
+ flex-shrink: 0;
813
+
814
+ svg {
815
+ width: 18px;
816
+ height: 18px;
817
+ flex-shrink: 0;
818
+ }
819
+
820
+ &:hover {
821
+ transform: translateY(-1px);
822
+ box-shadow: 0 4px 12px ${(props) => props.$danger ? "rgba(239, 68, 68, 0.3)" : props.$secondary ? "rgba(0,0,0,0.1)" : "rgba(124, 58, 237, 0.3)"};
823
+ }
824
+
825
+ &:active {
826
+ transform: translateY(0);
827
+ }
828
+
829
+ &:disabled {
830
+ opacity: 0.5;
831
+ cursor: not-allowed;
832
+ transform: none;
833
+ }
834
+
835
+ @media (max-width: 480px) {
836
+ width: 100%;
837
+ }
838
+ `;
839
+ const PermissionsList = styled.div`
840
+ display: none;
841
+
842
+ @media (max-width: 768px) {
843
+ display: flex;
844
+ flex-direction: column;
845
+ gap: 12px;
846
+ }
847
+ `;
848
+ const PermissionCard = styled.div`
849
+ background: ${(props) => props.theme.colors.neutral100};
850
+ border: 1px solid ${(props) => props.theme.colors.neutral200};
851
+ border-radius: 12px;
852
+ padding: 16px;
853
+ `;
854
+ const PermissionCardHeader = styled.div`
855
+ display: flex;
856
+ align-items: center;
857
+ justify-content: space-between;
858
+ margin-bottom: 12px;
859
+ `;
860
+ const PermissionCardBody = styled.div`
861
+ display: flex;
862
+ flex-direction: column;
863
+ gap: 12px;
864
+ `;
865
+ const PermissionRow = styled.div`
866
+ display: flex;
867
+ justify-content: space-between;
868
+ align-items: center;
869
+ gap: 8px;
870
+ `;
871
+ const PermissionLabel = styled.span`
872
+ font-size: 12px;
873
+ font-weight: 600;
874
+ color: ${(props) => props.theme.colors.neutral600};
875
+ text-transform: uppercase;
876
+ `;
877
+ const Table = styled.table`
878
+ width: 100%;
879
+ border-collapse: collapse;
880
+ min-width: 600px;
881
+
882
+ @media (max-width: 768px) {
883
+ display: none;
884
+ }
885
+ `;
886
+ const Th = styled.th`
887
+ text-align: left;
888
+ padding: 12px 16px;
889
+ font-size: 13px;
890
+ font-weight: 600;
891
+ color: ${(props) => props.theme.colors.neutral600};
892
+ text-transform: uppercase;
893
+ letter-spacing: 0.5px;
894
+ border-bottom: 2px solid ${(props) => props.theme.colors.neutral150};
895
+ white-space: nowrap;
896
+ `;
897
+ const Td = styled.td`
898
+ padding: 16px;
899
+ border-bottom: 1px solid ${(props) => props.theme.colors.neutral150};
900
+ font-size: 14px;
901
+ color: ${(props) => props.theme.colors.neutral800};
902
+ `;
903
+ const UserInfo = styled.div`
904
+ display: flex;
905
+ align-items: center;
906
+ gap: 12px;
907
+ `;
908
+ const Avatar = styled.div`
909
+ width: clamp(36px, 5vw, 40px);
910
+ height: clamp(36px, 5vw, 40px);
911
+ border-radius: 50%;
912
+ background: linear-gradient(135deg, #7C3AED 0%, #6d28d9 100%);
913
+ display: flex;
914
+ align-items: center;
915
+ justify-content: center;
916
+ color: white;
917
+ font-weight: 600;
918
+ font-size: clamp(12px, 2vw, 14px);
919
+ flex-shrink: 0;
920
+ `;
921
+ const UserDetails = styled.div`
922
+ display: flex;
923
+ flex-direction: column;
924
+ min-width: 0;
925
+ `;
926
+ const UserName = styled.div`
927
+ font-weight: 600;
928
+ color: ${(props) => props.theme.colors.neutral800};
929
+ font-size: clamp(13px, 2vw, 14px);
930
+ `;
931
+ const UserEmail = styled.div`
932
+ font-size: clamp(11px, 1.5vw, 13px);
933
+ color: ${(props) => props.theme.colors.neutral600};
934
+ overflow: hidden;
935
+ text-overflow: ellipsis;
936
+ white-space: nowrap;
937
+ max-width: 200px;
938
+
939
+ @media (max-width: 480px) {
940
+ max-width: 150px;
941
+ }
942
+ `;
943
+ styled.span`
944
+ display: inline-flex;
945
+ align-items: center;
946
+ gap: 6px;
947
+ padding: 6px 12px;
948
+ border-radius: 20px;
949
+ font-size: 12px;
950
+ font-weight: 600;
951
+ background: ${(props) => props.$role === "owner" ? "#7C3AED" : props.$role === "editor" ? "#10B981" : "#64748b"};
952
+ color: white;
953
+
954
+ svg {
955
+ width: 14px;
956
+ height: 14px;
957
+ }
958
+ `;
959
+ const Select = styled.select`
960
+ padding: clamp(6px, 1vw, 8px) clamp(10px, 1.5vw, 12px);
961
+ border: 1px solid ${(props) => props.theme.colors.neutral200};
962
+ border-radius: 8px;
963
+ font-size: clamp(12px, 2vw, 14px);
964
+ color: ${(props) => props.theme.colors.neutral800};
965
+ background: ${(props) => props.theme.colors.neutral0};
966
+ cursor: pointer;
967
+ max-width: 100%;
968
+
969
+ &:focus {
970
+ outline: none;
971
+ border-color: #7C3AED;
972
+ }
973
+ `;
974
+ const EmptyState = styled.div`
975
+ text-align: center;
976
+ padding: clamp(40px, 6vw, 60px) 20px;
977
+ color: ${(props) => props.theme.colors.neutral500};
978
+
979
+ h3 {
980
+ font-size: clamp(16px, 2.5vw, 18px);
981
+ margin: 0 0 8px;
982
+ color: ${(props) => props.theme.colors.neutral600};
983
+ }
984
+
985
+ p {
986
+ font-size: clamp(13px, 2vw, 14px);
987
+ margin: 0;
988
+ }
989
+ `;
990
+ const EmptyIcon = styled.div`
991
+ width: clamp(60px, 10vw, 80px);
992
+ height: clamp(60px, 10vw, 80px);
993
+ margin: 0 auto 20px;
994
+ background: ${(props) => props.theme.colors.neutral100};
995
+ border-radius: 50%;
996
+ display: flex;
997
+ align-items: center;
998
+ justify-content: center;
999
+
1000
+ svg {
1001
+ width: clamp(30px, 5vw, 40px);
1002
+ height: clamp(30px, 5vw, 40px);
1003
+ color: ${(props) => props.theme.colors.neutral400};
1004
+ }
1005
+ `;
1006
+ const Modal = styled.div`
1007
+ position: fixed;
1008
+ top: 0;
1009
+ left: 0;
1010
+ right: 0;
1011
+ bottom: 0;
1012
+ background: rgba(15, 23, 42, 0.75);
1013
+ backdrop-filter: blur(8px);
1014
+ display: flex;
1015
+ align-items: center;
1016
+ justify-content: center;
1017
+ z-index: 10000;
1018
+ padding: 16px;
1019
+ animation: fadeIn 0.2s ease;
1020
+ overflow-y: auto;
1021
+
1022
+ @keyframes fadeIn {
1023
+ from { opacity: 0; }
1024
+ to { opacity: 1; }
1025
+ }
1026
+
1027
+ @media (max-width: 600px) {
1028
+ align-items: flex-start;
1029
+ padding-top: 20px;
1030
+ padding-bottom: 20px;
1031
+ }
1032
+ `;
1033
+ const ModalContent$1 = styled.div`
1034
+ background: ${(props) => props.theme.colors.neutral0};
1035
+ border-radius: clamp(16px, 3vw, 24px);
1036
+ padding: 0;
1037
+ max-width: 580px;
1038
+ width: 100%;
1039
+ max-height: calc(100vh - 40px);
1040
+ overflow-y: auto;
1041
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
1042
+ animation: slideUp 0.3s ease;
1043
+
1044
+ @keyframes slideUp {
1045
+ from {
1046
+ opacity: 0;
1047
+ transform: translateY(20px);
1048
+ }
1049
+ to {
1050
+ opacity: 1;
1051
+ transform: translateY(0);
1052
+ }
1053
+ }
1054
+
1055
+ @media (max-width: 600px) {
1056
+ max-height: none;
1057
+ border-radius: 16px;
1058
+ }
1059
+ `;
1060
+ const ModalHeader = styled.div`
1061
+ background: linear-gradient(135deg, #7C3AED 0%, #6d28d9 100%);
1062
+ padding: clamp(20px, 4vw, 32px);
1063
+ color: white;
1064
+ position: relative;
1065
+ overflow: hidden;
1066
+
1067
+ &::before {
1068
+ content: '';
1069
+ position: absolute;
1070
+ top: -50%;
1071
+ right: -10%;
1072
+ width: 200px;
1073
+ height: 200px;
1074
+ background: rgba(255, 255, 255, 0.1);
1075
+ border-radius: 50%;
1076
+ filter: blur(40px);
1077
+ }
1078
+ `;
1079
+ const ModalBody = styled.div`
1080
+ padding: clamp(20px, 4vw, 32px);
1081
+ `;
1082
+ const ModalTitle = styled.h3`
1083
+ font-size: clamp(18px, 3vw, 24px);
1084
+ font-weight: 700;
1085
+ margin: 0 0 8px 0;
1086
+ display: flex;
1087
+ align-items: center;
1088
+ gap: 12px;
1089
+ position: relative;
1090
+
1091
+ svg {
1092
+ width: clamp(22px, 3vw, 28px);
1093
+ height: clamp(22px, 3vw, 28px);
1094
+ flex-shrink: 0;
1095
+ }
1096
+ `;
1097
+ const ModalSubtitle = styled.p`
1098
+ font-size: clamp(13px, 2vw, 15px);
1099
+ margin: 0;
1100
+ opacity: 0.95;
1101
+ position: relative;
1102
+ `;
1103
+ const FormGroup = styled.div`
1104
+ margin-bottom: clamp(16px, 3vw, 24px);
1105
+ `;
1106
+ const Label = styled.label`
1107
+ display: block;
1108
+ font-size: clamp(13px, 2vw, 14px);
1109
+ font-weight: 600;
1110
+ color: ${(props) => props.theme.colors.neutral800};
1111
+ margin-bottom: 10px;
1112
+ `;
1113
+ const SelectWrapper = styled.div`
1114
+ position: relative;
1115
+ `;
1116
+ const StyledSelect = styled.select`
1117
+ width: 100%;
1118
+ padding: clamp(12px, 2vw, 14px) clamp(14px, 2vw, 16px);
1119
+ border: 2px solid ${(props) => props.theme.colors.neutral200};
1120
+ border-radius: 12px;
1121
+ font-size: clamp(14px, 2vw, 15px);
1122
+ color: ${(props) => props.theme.colors.neutral800};
1123
+ background: ${(props) => props.theme.colors.neutral0};
1124
+ cursor: pointer;
1125
+ transition: all 0.2s ease;
1126
+ appearance: none;
1127
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");
1128
+ background-repeat: no-repeat;
1129
+ background-position: right 12px center;
1130
+ background-size: 20px;
1131
+ padding-right: 40px;
1132
+
1133
+ &:hover {
1134
+ border-color: #a78bfa;
1135
+ }
1136
+
1137
+ &:focus {
1138
+ outline: none;
1139
+ border-color: #7C3AED;
1140
+ box-shadow: 0 0 0 4px rgba(124, 58, 237, 0.1);
1141
+ }
1142
+
1143
+ option {
1144
+ padding: 12px;
1145
+ }
1146
+ `;
1147
+ styled.input`
1148
+ width: 100%;
1149
+ padding: clamp(12px, 2vw, 14px) clamp(14px, 2vw, 16px);
1150
+ border: 2px solid ${(props) => props.theme.colors.neutral200};
1151
+ border-radius: 12px;
1152
+ font-size: clamp(14px, 2vw, 15px);
1153
+ color: ${(props) => props.theme.colors.neutral800};
1154
+ background: ${(props) => props.theme.colors.neutral0};
1155
+ transition: all 0.2s ease;
1156
+ box-sizing: border-box;
1157
+
1158
+ &:hover {
1159
+ border-color: #a78bfa;
1160
+ }
1161
+
1162
+ &:focus {
1163
+ outline: none;
1164
+ border-color: #7C3AED;
1165
+ box-shadow: 0 0 0 4px rgba(124, 58, 237, 0.1);
1166
+ }
1167
+
1168
+ &::placeholder {
1169
+ color: ${(props) => props.theme.colors.neutral500};
1170
+ }
1171
+ `;
1172
+ const RoleOption = styled.div`
1173
+ display: flex;
1174
+ align-items: center;
1175
+ gap: clamp(10px, 2vw, 12px);
1176
+ padding: clamp(12px, 2vw, 16px);
1177
+ border: 2px solid ${(props) => props.$selected ? "#7C3AED" : props.theme.colors.neutral200};
1178
+ border-radius: 12px;
1179
+ cursor: pointer;
1180
+ transition: all 0.2s ease;
1181
+ background: ${(props) => props.$selected ? "rgba(124, 58, 237, 0.05)" : props.theme.colors.neutral0};
1182
+
1183
+ &:hover {
1184
+ border-color: #7C3AED;
1185
+ background: rgba(124, 58, 237, 0.03);
1186
+ }
1187
+
1188
+ &:active {
1189
+ transform: scale(0.99);
1190
+ }
1191
+ `;
1192
+ const RoleIcon = styled.div`
1193
+ font-size: clamp(18px, 3vw, 24px);
1194
+ width: clamp(40px, 6vw, 48px);
1195
+ height: clamp(40px, 6vw, 48px);
1196
+ display: flex;
1197
+ align-items: center;
1198
+ justify-content: center;
1199
+ background: ${(props) => props.$role === "owner" ? "linear-gradient(135deg, #FFD700 0%, #FFA500 100%)" : props.$role === "editor" ? "linear-gradient(135deg, #10B981 0%, #059669 100%)" : "linear-gradient(135deg, #64748b 0%, #475569 100%)"};
1200
+ border-radius: 12px;
1201
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
1202
+ flex-shrink: 0;
1203
+ `;
1204
+ const RoleInfo = styled.div`
1205
+ flex: 1;
1206
+ min-width: 0;
1207
+ `;
1208
+ const RoleName = styled.div`
1209
+ font-weight: 600;
1210
+ color: ${(props) => props.theme.colors.neutral800};
1211
+ font-size: clamp(14px, 2vw, 16px);
1212
+ margin-bottom: 4px;
1213
+ `;
1214
+ const RoleDescription = styled.div`
1215
+ font-size: clamp(11px, 1.5vw, 13px);
1216
+ color: ${(props) => props.theme.colors.neutral600};
1217
+ line-height: 1.4;
1218
+ `;
1219
+ const RoleGrid = styled.div`
1220
+ display: grid;
1221
+ gap: 12px;
1222
+ margin-bottom: clamp(16px, 3vw, 24px);
1223
+ `;
1224
+ const ModalActions = styled.div`
1225
+ display: flex;
1226
+ gap: 12px;
1227
+ margin-top: clamp(16px, 3vw, 24px);
1228
+ flex-wrap: wrap;
1229
+
1230
+ @media (max-width: 400px) {
1231
+ flex-direction: column;
1232
+
1233
+ button {
1234
+ width: 100%;
1235
+ }
1236
+ }
1237
+ `;
1238
+ const LoadingContainer = styled.div`
1239
+ display: flex;
1240
+ align-items: center;
1241
+ justify-content: center;
1242
+ padding: clamp(40px, 6vw, 60px);
1243
+ `;
1244
+ const HelpText = styled.small`
1245
+ display: block;
1246
+ margin-top: 8px;
1247
+ font-size: clamp(11px, 1.5vw, 12px);
1248
+ color: ${(props) => props.$warning ? "#f59e0b" : props.theme.colors.neutral600};
1249
+ line-height: 1.4;
1250
+ `;
1251
+ styled.span`
1252
+ display: inline-block;
1253
+ background: ${(props) => props.theme.colors.neutral100};
1254
+ color: #7C3AED;
1255
+ padding: 4px 10px;
1256
+ border-radius: 6px;
1257
+ font-size: clamp(11px, 1.5vw, 13px);
1258
+ font-weight: 500;
1259
+ max-width: 180px;
1260
+ overflow: hidden;
1261
+ text-overflow: ellipsis;
1262
+ white-space: nowrap;
1263
+
1264
+ @media (max-width: 480px) {
1265
+ max-width: 120px;
1266
+ }
1267
+ `;
1268
+ const CollaborationSettings = () => {
1269
+ const { formatMessage } = useIntl();
1270
+ const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
1271
+ const { get, post, put, del } = useFetchClient();
1272
+ const [loading, setLoading] = useState(true);
1273
+ const [permissions, setPermissions] = useState([]);
1274
+ const [users, setUsers] = useState([]);
1275
+ const [contentTypes, setContentTypes] = useState([]);
1276
+ const [showAddModal, setShowAddModal] = useState(false);
1277
+ const [selectedUser, setSelectedUser] = useState("");
1278
+ const [selectedRole, setSelectedRole] = useState("editor");
1279
+ const [contentType, setContentType] = useState("");
1280
+ const [saving, setSaving] = useState(false);
1281
+ const [limits, setLimits] = useState({ current: 0, max: 2, unlimited: false, canAdd: true });
1282
+ useEffect(() => {
1283
+ loadData();
1284
+ loadLimits();
1285
+ }, []);
1286
+ const loadLimits = async () => {
1287
+ try {
1288
+ const response = await get("/magic-editor-x/license/limits");
1289
+ if (response.data?.limits?.collaborators) {
1290
+ setLimits(response.data.limits.collaborators);
1291
+ }
1292
+ } catch (error) {
1293
+ console.error("[Collab Settings] Error loading limits:", error);
1294
+ }
1295
+ };
1296
+ const loadData = async () => {
1297
+ setLoading(true);
1298
+ try {
1299
+ const [permsRes, usersRes, typesRes] = await Promise.all([
1300
+ get("/magic-editor-x/collaboration/permissions"),
1301
+ get("/magic-editor-x/collaboration/users"),
1302
+ get("/content-type-builder/content-types")
1303
+ ]);
1304
+ setPermissions(permsRes.data?.data || permsRes.data || []);
1305
+ setUsers(usersRes.data?.data || usersRes.data || []);
1306
+ const allTypes = typesRes.data?.data || typesRes.data || [];
1307
+ console.log("[Collab] All content types from API:", allTypes);
1308
+ const filteredTypes = allTypes.filter((type) => {
1309
+ const uid = type.uid || "";
1310
+ if (!uid.startsWith("api::")) {
1311
+ return false;
1312
+ }
1313
+ const schema = type.schema || type;
1314
+ const attributes = schema.attributes || type.attributes || {};
1315
+ const hasMagicEditorField = Object.entries(attributes).some(([fieldName, attr]) => {
1316
+ const customFieldValue = attr.customField || "";
1317
+ const isMagicEditor = customFieldValue.includes("magic-editor-x");
1318
+ if (isMagicEditor) {
1319
+ console.log(`[Collab] ✅ Found Magic Editor field: ${uid}.${fieldName}`, attr);
1320
+ }
1321
+ return isMagicEditor;
1322
+ });
1323
+ return hasMagicEditorField;
1324
+ }).map((type) => {
1325
+ const schema = type.schema || type;
1326
+ const attributes = schema.attributes || type.attributes || {};
1327
+ return {
1328
+ uid: type.uid,
1329
+ displayName: schema.info?.displayName || schema.info?.singularName || type.uid,
1330
+ singularName: schema.info?.singularName,
1331
+ pluralName: schema.info?.pluralName,
1332
+ kind: schema.kind || type.kind,
1333
+ // Find the magic editor field names
1334
+ magicEditorFields: Object.entries(attributes).filter(
1335
+ ([_, attr]) => (attr.customField || "").includes("magic-editor-x")
1336
+ ).map(([name]) => name)
1337
+ };
1338
+ }).sort((a, b) => a.displayName.localeCompare(b.displayName));
1339
+ setContentTypes(filteredTypes);
1340
+ console.log("[Collab] Content types with Magic Editor X:", filteredTypes);
1341
+ console.log("[Collab] Loaded users:", usersRes.data);
1342
+ console.log("[Collab] Loaded permissions:", permsRes.data);
1343
+ console.log("[Collab] Loaded content types:", filteredTypes);
1344
+ } catch (error) {
1345
+ console.error("[Collab Settings] Load error:", error);
1346
+ alert(t("collaboration.errorLoading", "Error loading: {error}", { error: error.message || "Unknown error" }));
1347
+ } finally {
1348
+ setLoading(false);
1349
+ }
1350
+ };
1351
+ const handleAddPermission = async () => {
1352
+ if (!selectedUser || !selectedRole) return;
1353
+ setSaving(true);
1354
+ try {
1355
+ await post("/magic-editor-x/collaboration/permissions", {
1356
+ userId: selectedUser,
1357
+ role: selectedRole,
1358
+ contentType: contentType || "*",
1359
+ entryId: null,
1360
+ fieldName: null
1361
+ });
1362
+ await loadData();
1363
+ await loadLimits();
1364
+ setShowAddModal(false);
1365
+ setSelectedUser("");
1366
+ setSelectedRole("editor");
1367
+ setContentType("");
1368
+ } catch (error) {
1369
+ console.error("[Collab Settings] Add error:", error);
1370
+ if (error.response?.data?.upgradeRequired) {
1371
+ alert(t("collaboration.limitReachedAlert", "Collaborator limit reached.\n\nUpgrade at https://store.magicdx.dev/ for more collaborators."));
1372
+ } else {
1373
+ alert(t("collaboration.errorAdding", "Error adding permission"));
1374
+ }
1375
+ } finally {
1376
+ setSaving(false);
1377
+ }
1378
+ };
1379
+ const handleOpenAddModal = () => {
1380
+ if (!limits.canAdd && !limits.unlimited) {
1381
+ alert(t("collaboration.limitReachedAlert", "Collaborator limit reached ({current}/{max}).\n\nUpgrade at https://store.magicdx.dev/ for more collaborators.", { current: limits.current, max: limits.max }));
1382
+ return;
1383
+ }
1384
+ setShowAddModal(true);
1385
+ };
1386
+ const handleUpdateRole = async (permissionId, newRole) => {
1387
+ try {
1388
+ await put(`/magic-editor-x/collaboration/permissions/${permissionId}`, {
1389
+ role: newRole
1390
+ });
1391
+ await loadData();
1392
+ } catch (error) {
1393
+ console.error("[Collab Settings] Update error:", error);
1394
+ alert(t("collaboration.errorUpdating", "Error updating role"));
1395
+ }
1396
+ };
1397
+ const handleUpdateContentType = async (permissionId, newContentType) => {
1398
+ try {
1399
+ await put(`/magic-editor-x/collaboration/permissions/${permissionId}`, {
1400
+ contentType: newContentType === "*" ? null : newContentType
1401
+ });
1402
+ await loadData();
1403
+ } catch (error) {
1404
+ console.error("[Collab Settings] Update content type error:", error);
1405
+ alert(t("collaboration.errorUpdating", "Error updating role"));
1406
+ }
1407
+ };
1408
+ const handleDeletePermission = async (permissionId) => {
1409
+ if (!confirm(t("collaboration.confirmDelete", "Really remove permission?"))) return;
1410
+ try {
1411
+ await del(`/magic-editor-x/collaboration/permissions/${permissionId}`);
1412
+ await loadData();
1413
+ await loadLimits();
1414
+ } catch (error) {
1415
+ console.error("[Collab Settings] Delete error:", error);
1416
+ alert(t("collaboration.errorDeleting", "Error deleting permission"));
1417
+ }
1418
+ };
1419
+ const getUserInitials = (user) => {
1420
+ if (!user) return "?";
1421
+ const first = (user.firstname?.[0] || user.email?.[0] || "?").toUpperCase();
1422
+ const last = (user.lastname?.[0] || "").toUpperCase();
1423
+ return `${first}${last}`.trim();
1424
+ };
1425
+ if (loading) {
1426
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(LoadingContainer, { children: /* @__PURE__ */ jsx(Loader, {}) }) });
1427
+ }
1428
+ return /* @__PURE__ */ jsxs(Container, { children: [
1429
+ /* @__PURE__ */ jsxs(Header, { children: [
1430
+ /* @__PURE__ */ jsxs(Title, { children: [
1431
+ /* @__PURE__ */ jsx(UserGroupIcon, {}),
1432
+ t("collaboration.title", "Collaboration")
1433
+ ] }),
1434
+ /* @__PURE__ */ jsx(Subtitle, { children: t("collaboration.subtitle", "Manage permissions for real-time editing") })
1435
+ ] }),
1436
+ !limits.unlimited && /* @__PURE__ */ jsx(Card, { style: { marginBottom: "16px", background: limits.canAdd ? "#f0fdf4" : "#fef2f2", borderColor: limits.canAdd ? "#bbf7d0" : "#fecaca" }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: "12px" }, children: [
1437
+ /* @__PURE__ */ jsxs("div", { children: [
1438
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 600, marginBottom: "4px" }, children: t("collaboration.limitInfo", "Collaborators: {current} / {max}", { current: limits.current, max: limits.max }) }),
1439
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "13px", color: "#6b7280" }, children: limits.canAdd ? t("collaboration.limitCanAdd", "You can add {remaining} more collaborator(s).", { remaining: limits.max - limits.current }) : t("collaboration.limitReached", "Limit reached. Upgrade for more collaborators.") })
1440
+ ] }),
1441
+ !limits.canAdd && /* @__PURE__ */ jsx(
1442
+ Button,
1443
+ {
1444
+ onClick: () => window.open("https://store.magicdx.dev/", "_blank"),
1445
+ style: { background: "linear-gradient(135deg, #7C3AED, #6d28d9)", color: "white" },
1446
+ children: t("collaboration.upgrade", "Upgrade")
1447
+ }
1448
+ )
1449
+ ] }) }),
1450
+ /* @__PURE__ */ jsxs(Card, { children: [
1451
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
1452
+ /* @__PURE__ */ jsx(CardTitle, { children: t("collaboration.authorizedUsers", "Authorized Users ({count})", { count: permissions.length }) }),
1453
+ /* @__PURE__ */ jsxs(Button, { onClick: handleOpenAddModal, disabled: !limits.canAdd && !limits.unlimited, children: [
1454
+ /* @__PURE__ */ jsx(UserPlusIcon, {}),
1455
+ t("collaboration.addUser", "Add User")
1456
+ ] })
1457
+ ] }),
1458
+ permissions.length === 0 ? /* @__PURE__ */ jsxs(EmptyState, { children: [
1459
+ /* @__PURE__ */ jsx(EmptyIcon, { children: /* @__PURE__ */ jsx(UserGroupIcon, {}) }),
1460
+ /* @__PURE__ */ jsx("h3", { children: t("collaboration.noPermissions", "No Permissions") }),
1461
+ /* @__PURE__ */ jsx("p", { children: t("collaboration.noPermissions.description", "Add users to enable collaboration") })
1462
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1463
+ /* @__PURE__ */ jsxs(Table, { children: [
1464
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
1465
+ /* @__PURE__ */ jsx(Th, { children: t("collaboration.user", "User") }),
1466
+ /* @__PURE__ */ jsx(Th, { children: t("collaboration.role", "Role") }),
1467
+ /* @__PURE__ */ jsx(Th, { children: t("collaboration.contentType", "Content Type") }),
1468
+ /* @__PURE__ */ jsx(Th, { children: t("collaboration.actions", "Actions") })
1469
+ ] }) }),
1470
+ /* @__PURE__ */ jsx("tbody", { children: permissions.map((perm) => /* @__PURE__ */ jsxs("tr", { children: [
1471
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(UserInfo, { children: [
1472
+ /* @__PURE__ */ jsx(Avatar, { children: getUserInitials(perm.user) }),
1473
+ /* @__PURE__ */ jsxs(UserDetails, { children: [
1474
+ /* @__PURE__ */ jsxs(UserName, { children: [
1475
+ perm.user?.firstname,
1476
+ " ",
1477
+ perm.user?.lastname
1478
+ ] }),
1479
+ /* @__PURE__ */ jsx(UserEmail, { children: perm.user?.email })
1480
+ ] })
1481
+ ] }) }),
1482
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(
1483
+ Select,
1484
+ {
1485
+ value: perm.role,
1486
+ onChange: (e) => handleUpdateRole(perm.documentId, e.target.value),
1487
+ children: [
1488
+ /* @__PURE__ */ jsxs("option", { value: "viewer", children: [
1489
+ "👁️ ",
1490
+ t("role.viewer", "Viewer")
1491
+ ] }),
1492
+ /* @__PURE__ */ jsxs("option", { value: "editor", children: [
1493
+ "✏️ ",
1494
+ t("role.editor", "Editor")
1495
+ ] }),
1496
+ /* @__PURE__ */ jsxs("option", { value: "owner", children: [
1497
+ "👑 ",
1498
+ t("role.owner", "Owner")
1499
+ ] })
1500
+ ]
1501
+ }
1502
+ ) }),
1503
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(
1504
+ Select,
1505
+ {
1506
+ value: perm.contentType || "*",
1507
+ onChange: (e) => handleUpdateContentType(perm.documentId, e.target.value),
1508
+ style: { minWidth: "160px" },
1509
+ children: [
1510
+ /* @__PURE__ */ jsxs("option", { value: "*", children: [
1511
+ "🌐 ",
1512
+ t("collaboration.allContentTypes", "All Content Types with Magic Editor")
1513
+ ] }),
1514
+ contentTypes.map((type) => /* @__PURE__ */ jsxs("option", { value: type.uid, children: [
1515
+ type.kind === "singleType" ? "📄" : "📚",
1516
+ " ",
1517
+ type.displayName
1518
+ ] }, type.uid))
1519
+ ]
1520
+ }
1521
+ ) }),
1522
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(
1523
+ Button,
1524
+ {
1525
+ $danger: true,
1526
+ onClick: () => handleDeletePermission(perm.documentId),
1527
+ style: { padding: "8px 12px" },
1528
+ children: /* @__PURE__ */ jsx(TrashIcon, {})
1529
+ }
1530
+ ) })
1531
+ ] }, perm.documentId)) })
1532
+ ] }),
1533
+ /* @__PURE__ */ jsx(PermissionsList, { children: permissions.map((perm) => /* @__PURE__ */ jsxs(PermissionCard, { children: [
1534
+ /* @__PURE__ */ jsxs(PermissionCardHeader, { children: [
1535
+ /* @__PURE__ */ jsxs(UserInfo, { children: [
1536
+ /* @__PURE__ */ jsx(Avatar, { children: getUserInitials(perm.user) }),
1537
+ /* @__PURE__ */ jsxs(UserDetails, { children: [
1538
+ /* @__PURE__ */ jsxs(UserName, { children: [
1539
+ perm.user?.firstname,
1540
+ " ",
1541
+ perm.user?.lastname
1542
+ ] }),
1543
+ /* @__PURE__ */ jsx(UserEmail, { children: perm.user?.email })
1544
+ ] })
1545
+ ] }),
1546
+ /* @__PURE__ */ jsx(
1547
+ Button,
1548
+ {
1549
+ $danger: true,
1550
+ onClick: () => handleDeletePermission(perm.documentId),
1551
+ style: { padding: "8px 12px" },
1552
+ children: /* @__PURE__ */ jsx(TrashIcon, {})
1553
+ }
1554
+ )
1555
+ ] }),
1556
+ /* @__PURE__ */ jsxs(PermissionCardBody, { children: [
1557
+ /* @__PURE__ */ jsxs(PermissionRow, { children: [
1558
+ /* @__PURE__ */ jsx(PermissionLabel, { children: t("collaboration.role", "Role") }),
1559
+ /* @__PURE__ */ jsxs(
1560
+ Select,
1561
+ {
1562
+ value: perm.role,
1563
+ onChange: (e) => handleUpdateRole(perm.documentId, e.target.value),
1564
+ children: [
1565
+ /* @__PURE__ */ jsxs("option", { value: "viewer", children: [
1566
+ "👁️ ",
1567
+ t("role.viewer", "Viewer")
1568
+ ] }),
1569
+ /* @__PURE__ */ jsxs("option", { value: "editor", children: [
1570
+ "✏️ ",
1571
+ t("role.editor", "Editor")
1572
+ ] }),
1573
+ /* @__PURE__ */ jsxs("option", { value: "owner", children: [
1574
+ "👑 ",
1575
+ t("role.owner", "Owner")
1576
+ ] })
1577
+ ]
1578
+ }
1579
+ )
1580
+ ] }),
1581
+ /* @__PURE__ */ jsxs(PermissionRow, { children: [
1582
+ /* @__PURE__ */ jsx(PermissionLabel, { children: t("collaboration.contentType", "Content Type") }),
1583
+ /* @__PURE__ */ jsxs(
1584
+ Select,
1585
+ {
1586
+ value: perm.contentType || "*",
1587
+ onChange: (e) => handleUpdateContentType(perm.documentId, e.target.value),
1588
+ children: [
1589
+ /* @__PURE__ */ jsxs("option", { value: "*", children: [
1590
+ "🌐 ",
1591
+ t("collaboration.allContentTypes", "All Content Types with Magic Editor")
1592
+ ] }),
1593
+ contentTypes.map((type) => /* @__PURE__ */ jsxs("option", { value: type.uid, children: [
1594
+ type.kind === "singleType" ? "📄" : "📚",
1595
+ " ",
1596
+ type.displayName
1597
+ ] }, type.uid))
1598
+ ]
1599
+ }
1600
+ )
1601
+ ] })
1602
+ ] })
1603
+ ] }, perm.documentId)) })
1604
+ ] })
1605
+ ] }),
1606
+ showAddModal && /* @__PURE__ */ jsx(Modal, { onClick: () => setShowAddModal(false), children: /* @__PURE__ */ jsxs(ModalContent$1, { onClick: (e) => e.stopPropagation(), children: [
1607
+ /* @__PURE__ */ jsxs(ModalHeader, { children: [
1608
+ /* @__PURE__ */ jsxs(ModalTitle, { children: [
1609
+ /* @__PURE__ */ jsx(UserPlusIcon, {}),
1610
+ t("collaboration.inviteUser", "Invite User")
1611
+ ] }),
1612
+ /* @__PURE__ */ jsx(ModalSubtitle, { children: t("collaboration.inviteUser.subtitle", "Grant access to real-time editing") })
1613
+ ] }),
1614
+ /* @__PURE__ */ jsxs(ModalBody, { children: [
1615
+ /* @__PURE__ */ jsxs(FormGroup, { children: [
1616
+ /* @__PURE__ */ jsx(Label, { children: t("collaboration.selectUser", "Select User") }),
1617
+ /* @__PURE__ */ jsx(SelectWrapper, { children: /* @__PURE__ */ jsxs(
1618
+ StyledSelect,
1619
+ {
1620
+ value: selectedUser,
1621
+ onChange: (e) => setSelectedUser(e.target.value),
1622
+ children: [
1623
+ /* @__PURE__ */ jsx("option", { value: "", children: t("collaboration.selectUser.placeholder", "Choose a user...") }),
1624
+ users.map((user) => /* @__PURE__ */ jsxs("option", { value: user.id, children: [
1625
+ user.firstname,
1626
+ " ",
1627
+ user.lastname,
1628
+ " • ",
1629
+ user.email
1630
+ ] }, user.id))
1631
+ ]
1632
+ }
1633
+ ) })
1634
+ ] }),
1635
+ /* @__PURE__ */ jsxs(FormGroup, { children: [
1636
+ /* @__PURE__ */ jsx(Label, { children: t("collaboration.rolePermissions", "Role & Permissions") }),
1637
+ /* @__PURE__ */ jsxs(RoleGrid, { children: [
1638
+ /* @__PURE__ */ jsxs(
1639
+ RoleOption,
1640
+ {
1641
+ $selected: selectedRole === "viewer",
1642
+ onClick: () => setSelectedRole("viewer"),
1643
+ children: [
1644
+ /* @__PURE__ */ jsx(RoleIcon, { $role: "viewer", children: "👁️" }),
1645
+ /* @__PURE__ */ jsxs(RoleInfo, { children: [
1646
+ /* @__PURE__ */ jsx(RoleName, { children: t("role.viewer", "Viewer") }),
1647
+ /* @__PURE__ */ jsx(RoleDescription, { children: t("role.viewer.description", "Can view changes but not edit") })
1648
+ ] })
1649
+ ]
1650
+ }
1651
+ ),
1652
+ /* @__PURE__ */ jsxs(
1653
+ RoleOption,
1654
+ {
1655
+ $selected: selectedRole === "editor",
1656
+ onClick: () => setSelectedRole("editor"),
1657
+ children: [
1658
+ /* @__PURE__ */ jsx(RoleIcon, { $role: "editor", children: "✏️" }),
1659
+ /* @__PURE__ */ jsxs(RoleInfo, { children: [
1660
+ /* @__PURE__ */ jsx(RoleName, { children: t("role.editor", "Editor") }),
1661
+ /* @__PURE__ */ jsx(RoleDescription, { children: t("role.editor.description", "Can edit content and collaborate with others") })
1662
+ ] })
1663
+ ]
1664
+ }
1665
+ ),
1666
+ /* @__PURE__ */ jsxs(
1667
+ RoleOption,
1668
+ {
1669
+ $selected: selectedRole === "owner",
1670
+ onClick: () => setSelectedRole("owner"),
1671
+ children: [
1672
+ /* @__PURE__ */ jsx(RoleIcon, { $role: "owner", children: "👑" }),
1673
+ /* @__PURE__ */ jsxs(RoleInfo, { children: [
1674
+ /* @__PURE__ */ jsx(RoleName, { children: t("role.owner", "Owner") }),
1675
+ /* @__PURE__ */ jsx(RoleDescription, { children: t("role.owner.description", "Full access including managing permissions") })
1676
+ ] })
1677
+ ]
1678
+ }
1679
+ )
1680
+ ] })
1681
+ ] }),
1682
+ /* @__PURE__ */ jsxs(FormGroup, { children: [
1683
+ /* @__PURE__ */ jsx(Label, { children: t("collaboration.contentTypeOptional", "Content Type (optional)") }),
1684
+ /* @__PURE__ */ jsx(SelectWrapper, { children: /* @__PURE__ */ jsxs(
1685
+ StyledSelect,
1686
+ {
1687
+ value: contentType,
1688
+ onChange: (e) => setContentType(e.target.value),
1689
+ children: [
1690
+ /* @__PURE__ */ jsxs("option", { value: "", children: [
1691
+ "🌐 ",
1692
+ t("collaboration.allContentTypes", "All Content Types with Magic Editor")
1693
+ ] }),
1694
+ contentTypes.map((type) => /* @__PURE__ */ jsxs("option", { value: type.uid, children: [
1695
+ type.kind === "singleType" ? "📄" : "📚",
1696
+ " ",
1697
+ type.displayName,
1698
+ type.magicEditorFields?.length > 0 && ` (${type.magicEditorFields.join(", ")})`
1699
+ ] }, type.uid))
1700
+ ]
1701
+ }
1702
+ ) }),
1703
+ contentTypes.length === 0 ? /* @__PURE__ */ jsx(HelpText, { $warning: true, children: t("collaboration.contentTypeWarning", "⚠️ No content type currently uses the Magic Editor X field. Add the custom field to a content type.") }) : /* @__PURE__ */ jsx(HelpText, { children: t("collaboration.contentTypeHelp", "Shows only content types with Magic Editor X field • Empty = access to all") })
1704
+ ] }),
1705
+ /* @__PURE__ */ jsxs(ModalActions, { children: [
1706
+ /* @__PURE__ */ jsx(Button, { $secondary: true, onClick: () => setShowAddModal(false), children: t("collaboration.cancel", "Cancel") }),
1707
+ /* @__PURE__ */ jsxs(Button, { onClick: handleAddPermission, disabled: !selectedUser || saving, children: [
1708
+ /* @__PURE__ */ jsx(CheckCircleIcon, {}),
1709
+ saving ? t("collaboration.saving", "Saving...") : t("collaboration.invite", "Invite")
1710
+ ] })
1711
+ ] })
1712
+ ] })
1713
+ ] }) })
1714
+ ] });
1715
+ };
1716
+ const fadeIn = keyframes`
1717
+ from { opacity: 0; }
1718
+ to { opacity: 1; }
1719
+ `;
1720
+ const slideUp = keyframes`
1721
+ from {
1722
+ opacity: 0;
1723
+ transform: translateY(30px);
1724
+ }
1725
+ to {
1726
+ opacity: 1;
1727
+ transform: translateY(0);
1728
+ }
1729
+ `;
1730
+ const ModalOverlay = styled.div`
1731
+ position: fixed;
1732
+ top: 0;
1733
+ left: 0;
1734
+ right: 0;
1735
+ bottom: 0;
1736
+ background: rgba(4, 28, 47, 0.85);
1737
+ backdrop-filter: blur(8px);
1738
+ z-index: 9999;
1739
+ display: flex;
1740
+ align-items: center;
1741
+ justify-content: center;
1742
+ animation: ${fadeIn} 0.3s ease-out;
1743
+ padding: 20px;
1744
+ `;
1745
+ const ModalContent = styled(Box)`
1746
+ background: white;
1747
+ border-radius: 16px;
1748
+ width: 100%;
1749
+ max-width: 580px;
1750
+ box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
1751
+ animation: ${slideUp} 0.4s cubic-bezier(0.4, 0, 0.2, 1);
1752
+ overflow: hidden;
1753
+ `;
1754
+ const GradientHeader = styled(Box)`
1755
+ background: linear-gradient(135deg, #7C3AED 0%, #6d28d9 100%);
1756
+ padding: 32px 40px;
1757
+ position: relative;
1758
+ overflow: hidden;
1759
+
1760
+ &::before {
1761
+ content: '';
1762
+ position: absolute;
1763
+ top: -50%;
1764
+ right: -50%;
1765
+ width: 200%;
1766
+ height: 200%;
1767
+ background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
1768
+ }
1769
+ `;
1770
+ const IconWrapper = styled.div`
1771
+ width: 72px;
1772
+ height: 72px;
1773
+ border-radius: 50%;
1774
+ background: rgba(255, 255, 255, 0.2);
1775
+ display: flex;
1776
+ align-items: center;
1777
+ justify-content: center;
1778
+ margin: 0 auto 16px;
1779
+ backdrop-filter: blur(10px);
1780
+ border: 2px solid rgba(255, 255, 255, 0.3);
1781
+
1782
+ svg {
1783
+ width: 36px;
1784
+ height: 36px;
1785
+ color: white;
1786
+ }
1787
+ `;
1788
+ const CloseButton = styled.button`
1789
+ position: absolute;
1790
+ top: 16px;
1791
+ right: 16px;
1792
+ background: rgba(255, 255, 255, 0.2);
1793
+ border: 2px solid rgba(255, 255, 255, 0.3);
1794
+ border-radius: 50%;
1795
+ width: 36px;
1796
+ height: 36px;
1797
+ display: flex;
1798
+ align-items: center;
1799
+ justify-content: center;
1800
+ cursor: pointer;
1801
+ transition: all 0.2s;
1802
+ z-index: 10;
1803
+
1804
+ svg {
1805
+ width: 20px;
1806
+ height: 20px;
1807
+ color: white;
1808
+ }
1809
+
1810
+ &:hover {
1811
+ background: rgba(255, 255, 255, 0.3);
1812
+ transform: scale(1.1);
1813
+ }
1814
+
1815
+ &:active {
1816
+ transform: scale(0.95);
1817
+ }
1818
+ `;
1819
+ const ToggleButton = styled.button`
1820
+ background: none;
1821
+ border: none;
1822
+ color: #7C3AED;
1823
+ font-size: 13px;
1824
+ font-weight: 600;
1825
+ cursor: pointer;
1826
+ padding: 8px 0;
1827
+ text-decoration: underline;
1828
+ transition: color 0.2s;
1829
+
1830
+ &:hover {
1831
+ color: #6d28d9;
1832
+ }
1833
+
1834
+ &:disabled {
1835
+ opacity: 0.5;
1836
+ cursor: not-allowed;
1837
+ }
1838
+ `;
1839
+ const InfoBox = styled(Box)`
1840
+ background: #f0fdf4;
1841
+ border: 2px solid #bbf7d0;
1842
+ border-radius: 8px;
1843
+ padding: 16px;
1844
+ margin-bottom: 20px;
1845
+ `;
1846
+ const LicenseGuard = ({ children }) => {
1847
+ const { formatMessage } = useIntl();
1848
+ const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
1849
+ const { get, post } = useFetchClient();
1850
+ const { toggleNotification } = useNotification();
1851
+ const navigate = useNavigate();
1852
+ const [isChecking, setIsChecking] = useState(true);
1853
+ const [needsLicense, setNeedsLicense] = useState(false);
1854
+ const [isCreating, setIsCreating] = useState(false);
1855
+ const [useExistingKey, setUseExistingKey] = useState(false);
1856
+ const [existingLicenseKey, setExistingLicenseKey] = useState("");
1857
+ const [existingEmail, setExistingEmail] = useState("");
1858
+ const [adminUser, setAdminUser] = useState(null);
1859
+ useEffect(() => {
1860
+ checkLicenseStatus();
1861
+ fetchAdminUser();
1862
+ }, []);
1863
+ const fetchAdminUser = async () => {
1864
+ try {
1865
+ const response = await get("/admin/users/me");
1866
+ const userData = response.data?.data || response.data;
1867
+ if (userData) {
1868
+ setAdminUser(userData);
1869
+ }
1870
+ } catch (error) {
1871
+ console.debug("[Magic Editor X] Could not fetch admin user");
1872
+ }
1873
+ };
1874
+ const checkLicenseStatus = async () => {
1875
+ setIsChecking(true);
1876
+ try {
1877
+ const response = await get("/magic-editor-x/license/status");
1878
+ if (response.data.valid || response.data.demo === false) {
1879
+ setNeedsLicense(false);
1880
+ } else {
1881
+ setNeedsLicense(true);
1882
+ }
1883
+ } catch (error) {
1884
+ console.error("[Magic Editor X] License check error:", error);
1885
+ setNeedsLicense(false);
1886
+ } finally {
1887
+ setIsChecking(false);
1888
+ }
1889
+ };
1890
+ const handleAutoCreateLicense = async (e) => {
1891
+ e.preventDefault();
1892
+ setIsCreating(true);
1893
+ try {
1894
+ const response = await post("/magic-editor-x/license/auto-create", {});
1895
+ if (response.data && response.data.success) {
1896
+ toggleNotification({
1897
+ type: "success",
1898
+ message: t("licenseGuard.success.created", "License created! Reloading...")
1899
+ });
1900
+ setNeedsLicense(false);
1901
+ setTimeout(() => {
1902
+ window.location.reload();
1903
+ }, 500);
1904
+ } else {
1905
+ throw new Error("Failed to auto-create license");
1906
+ }
1907
+ } catch (error) {
1908
+ console.error("[Magic Editor X] Error:", error);
1909
+ toggleNotification({
1910
+ type: "danger",
1911
+ message: t("licenseGuard.error.create", "Failed to create license. Try manual entry.")
1912
+ });
1913
+ setIsCreating(false);
1914
+ setUseExistingKey(true);
1915
+ }
1916
+ };
1917
+ const handleValidateExistingKey = async (e) => {
1918
+ e.preventDefault();
1919
+ if (!existingLicenseKey.trim() || !existingEmail.trim()) {
1920
+ toggleNotification({
1921
+ type: "warning",
1922
+ message: t("licenseGuard.error.required", "Please enter both license key and email address")
1923
+ });
1924
+ return;
1925
+ }
1926
+ setIsCreating(true);
1927
+ try {
1928
+ const response = await post("/magic-editor-x/license/store-key", {
1929
+ licenseKey: existingLicenseKey.trim(),
1930
+ email: existingEmail.trim()
1931
+ });
1932
+ if (response.data && response.data.success) {
1933
+ toggleNotification({
1934
+ type: "success",
1935
+ message: t("licenseGuard.success.activated", "License activated! Reloading...")
1936
+ });
1937
+ setNeedsLicense(false);
1938
+ setTimeout(() => {
1939
+ window.location.reload();
1940
+ }, 500);
1941
+ } else {
1942
+ throw new Error("Invalid license");
1943
+ }
1944
+ } catch (error) {
1945
+ toggleNotification({
1946
+ type: "danger",
1947
+ message: t("licenseGuard.error.invalid", "Invalid license key or email address")
1948
+ });
1949
+ setIsCreating(false);
1950
+ }
1951
+ };
1952
+ const handleSkip = () => {
1953
+ setNeedsLicense(false);
1954
+ };
1955
+ const handleClose = () => {
1956
+ navigate("/content-manager");
1957
+ };
1958
+ if (isChecking) {
1959
+ return /* @__PURE__ */ jsx(Box, { padding: 8, style: { textAlign: "center" }, children: /* @__PURE__ */ jsx(Loader, { children: t("license.checking", "Checking license...") }) });
1960
+ }
1961
+ if (needsLicense) {
1962
+ return /* @__PURE__ */ jsx(ModalOverlay, { children: /* @__PURE__ */ jsxs(ModalContent, { children: [
1963
+ /* @__PURE__ */ jsxs(GradientHeader, { children: [
1964
+ /* @__PURE__ */ jsx(CloseButton, { onClick: handleClose, type: "button", children: /* @__PURE__ */ jsx(XMarkIcon, {}) }),
1965
+ /* @__PURE__ */ jsx(IconWrapper, { children: /* @__PURE__ */ jsx(KeyIcon, {}) }),
1966
+ /* @__PURE__ */ jsxs(Box, { style: { textAlign: "center", position: "relative" }, children: [
1967
+ /* @__PURE__ */ jsx(
1968
+ Typography,
1969
+ {
1970
+ variant: "alpha",
1971
+ style: {
1972
+ color: "white",
1973
+ fontSize: "24px",
1974
+ fontWeight: "700",
1975
+ marginBottom: "12px",
1976
+ display: "block"
1977
+ },
1978
+ children: t("licenseGuard.title", "Activate Magic Editor X")
1979
+ }
1980
+ ),
1981
+ /* @__PURE__ */ jsx(
1982
+ Typography,
1983
+ {
1984
+ variant: "epsilon",
1985
+ style: {
1986
+ color: "rgba(255, 255, 255, 0.9)",
1987
+ fontSize: "14px",
1988
+ display: "block"
1989
+ },
1990
+ children: useExistingKey ? t("licenseGuard.subtitle.existing", "Enter your existing license key") : t("licenseGuard.subtitle.new", "Create a FREE license to start using the editor")
1991
+ }
1992
+ )
1993
+ ] })
1994
+ ] }),
1995
+ /* @__PURE__ */ jsx("form", { onSubmit: useExistingKey ? handleValidateExistingKey : handleAutoCreateLicense, children: /* @__PURE__ */ jsx(Box, { padding: 6, paddingLeft: 8, paddingRight: 8, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 5, style: { width: "100%" }, children: [
1996
+ /* @__PURE__ */ jsx(InfoBox, { children: /* @__PURE__ */ jsxs(Typography, { variant: "omega", style: { fontSize: "13px", lineHeight: "1.6" }, children: [
1997
+ "[FREE] ",
1998
+ t("licenseGuard.info", "The editor is completely FREE to use! Creating a license helps us track usage and provide better support. You get 2 collaborators included.")
1999
+ ] }) }),
2000
+ /* @__PURE__ */ jsx(Box, { style: { textAlign: "center", width: "100%" }, children: /* @__PURE__ */ jsx(
2001
+ ToggleButton,
2002
+ {
2003
+ type: "button",
2004
+ onClick: () => setUseExistingKey(!useExistingKey),
2005
+ disabled: isCreating,
2006
+ children: useExistingKey ? t("licenseGuard.toggleNew", "Create new license") : t("licenseGuard.toggleExisting", "Have a license key?")
2007
+ }
2008
+ ) }),
2009
+ useExistingKey ? /* @__PURE__ */ jsxs(Fragment, { children: [
2010
+ /* @__PURE__ */ jsxs(Box, { style: { width: "100%" }, children: [
2011
+ /* @__PURE__ */ jsxs(
2012
+ Typography,
2013
+ {
2014
+ variant: "pi",
2015
+ fontWeight: "bold",
2016
+ style: { marginBottom: "8px", display: "block" },
2017
+ children: [
2018
+ t("licenseGuard.email", "Email Address"),
2019
+ " *"
2020
+ ]
2021
+ }
2022
+ ),
2023
+ /* @__PURE__ */ jsx(
2024
+ TextInput,
2025
+ {
2026
+ placeholder: t("licenseGuard.email.placeholder", "admin@example.com"),
2027
+ type: "email",
2028
+ value: existingEmail,
2029
+ onChange: (e) => setExistingEmail(e.target.value),
2030
+ required: true,
2031
+ disabled: isCreating
2032
+ }
2033
+ )
2034
+ ] }),
2035
+ /* @__PURE__ */ jsxs(Box, { style: { width: "100%" }, children: [
2036
+ /* @__PURE__ */ jsxs(
2037
+ Typography,
2038
+ {
2039
+ variant: "pi",
2040
+ fontWeight: "bold",
2041
+ style: { marginBottom: "8px", display: "block" },
2042
+ children: [
2043
+ t("licenseGuard.licenseKey", "License Key"),
2044
+ " *"
2045
+ ]
2046
+ }
2047
+ ),
2048
+ /* @__PURE__ */ jsx(
2049
+ TextInput,
2050
+ {
2051
+ placeholder: t("licenseGuard.licenseKey.placeholder", "MAGIC-EDITOR-XXXX-XXXX-XXXX"),
2052
+ value: existingLicenseKey,
2053
+ onChange: (e) => setExistingLicenseKey(e.target.value),
2054
+ required: true,
2055
+ disabled: isCreating
2056
+ }
2057
+ )
2058
+ ] })
2059
+ ] }) : adminUser ? /* @__PURE__ */ jsxs(
2060
+ Box,
2061
+ {
2062
+ background: "success100",
2063
+ padding: 5,
2064
+ style: {
2065
+ borderRadius: "8px",
2066
+ border: "2px solid #DCFCE7",
2067
+ textAlign: "center"
2068
+ },
2069
+ children: [
2070
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", style: { marginBottom: "12px", display: "block" }, children: t("licenseGuard.readyToActivate", "Ready to activate with your account:") }),
2071
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", style: { marginBottom: "4px", display: "block" }, children: [
2072
+ adminUser.firstname || "Admin",
2073
+ " ",
2074
+ adminUser.lastname || "User"
2075
+ ] }),
2076
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: adminUser.email || "Loading..." })
2077
+ ]
2078
+ }
2079
+ ) : /* @__PURE__ */ jsxs(Box, { padding: 4, background: "neutral100", hasRadius: true, style: { textAlign: "center" }, children: [
2080
+ /* @__PURE__ */ jsx(Loader, { small: true }),
2081
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", marginTop: 2, children: t("licenseGuard.loadingUser", "Loading admin user data...") })
2082
+ ] }),
2083
+ /* @__PURE__ */ jsxs(Flex, { gap: 3, justifyContent: "center", style: { marginTop: "16px" }, children: [
2084
+ /* @__PURE__ */ jsx(
2085
+ Button$2,
2086
+ {
2087
+ variant: "tertiary",
2088
+ onClick: handleSkip,
2089
+ disabled: isCreating,
2090
+ children: t("licenseGuard.skip", "Skip for now")
2091
+ }
2092
+ ),
2093
+ useExistingKey ? /* @__PURE__ */ jsx(
2094
+ Button$2,
2095
+ {
2096
+ type: "submit",
2097
+ size: "L",
2098
+ startIcon: /* @__PURE__ */ jsx(CheckIcon, { style: { width: 20, height: 20 } }),
2099
+ loading: isCreating,
2100
+ disabled: isCreating || !existingLicenseKey.trim() || !existingEmail.trim(),
2101
+ style: {
2102
+ background: "linear-gradient(135deg, #7C3AED 0%, #6d28d9 100%)",
2103
+ color: "white",
2104
+ fontWeight: "600",
2105
+ border: "none"
2106
+ },
2107
+ children: t("licenseGuard.validate", "Validate License")
2108
+ }
2109
+ ) : /* @__PURE__ */ jsx(
2110
+ Button$2,
2111
+ {
2112
+ type: "submit",
2113
+ size: "L",
2114
+ startIcon: /* @__PURE__ */ jsx(CheckIcon, { style: { width: 20, height: 20 } }),
2115
+ loading: isCreating,
2116
+ disabled: isCreating || !adminUser,
2117
+ style: {
2118
+ background: "linear-gradient(135deg, #7C3AED 0%, #6d28d9 100%)",
2119
+ color: "white",
2120
+ fontWeight: "600",
2121
+ border: "none"
2122
+ },
2123
+ children: t("licenseGuard.activate", "Activate FREE License")
2124
+ }
2125
+ )
2126
+ ] })
2127
+ ] }) }) })
2128
+ ] }) });
2129
+ }
2130
+ return /* @__PURE__ */ jsx(Fragment, { children });
2131
+ };
2132
+ const App = () => {
2133
+ return /* @__PURE__ */ jsx(LicenseGuard, { children: /* @__PURE__ */ jsxs(Routes, { children: [
2134
+ /* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(HomePage, {}) }),
2135
+ /* @__PURE__ */ jsx(Route, { path: "collaboration", element: /* @__PURE__ */ jsx(CollaborationSettings, {}) }),
2136
+ /* @__PURE__ */ jsx(Route, { path: "license", element: /* @__PURE__ */ jsx(LicensePage, {}) }),
2137
+ /* @__PURE__ */ jsx(Route, { path: "*", element: /* @__PURE__ */ jsx(Page.Error, {}) })
2138
+ ] }) });
2139
+ };
2140
+ export {
2141
+ App,
2142
+ App as default
2143
+ };