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