@alpaca-editor/core 1.0.3896 → 1.0.3897
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ActionButton.js +2 -2
- package/dist/components/ActionButton.js.map +1 -1
- package/dist/components/ui/button.js +2 -2
- package/dist/components/ui/button.js.map +1 -1
- package/dist/config/config.js +37 -22
- package/dist/config/config.js.map +1 -1
- package/dist/editor/FieldListField.js +1 -1
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/Titlebar.js +2 -1
- package/dist/editor/Titlebar.js.map +1 -1
- package/dist/editor/client/EditorClient.d.ts +18 -2
- package/dist/editor/client/EditorClient.js +117 -1
- package/dist/editor/client/EditorClient.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +4 -1
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/itemsRepository.js +1 -1
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/client/operations.js +1 -1
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/control-center/About.d.ts +1 -0
- package/dist/editor/control-center/About.js +8 -0
- package/dist/editor/control-center/About.js.map +1 -0
- package/dist/editor/control-center/ControlCenterMenu.js +3 -0
- package/dist/editor/control-center/ControlCenterMenu.js.map +1 -1
- package/dist/editor/control-center/Info.d.ts +1 -0
- package/dist/editor/control-center/Info.js +10 -0
- package/dist/editor/control-center/Info.js.map +1 -0
- package/dist/editor/control-center/QuotaInfo.d.ts +1 -0
- package/dist/editor/control-center/QuotaInfo.js +52 -0
- package/dist/editor/control-center/QuotaInfo.js.map +1 -0
- package/dist/editor/control-center/Status.js +69 -2
- package/dist/editor/control-center/Status.js.map +1 -1
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js +7 -6
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +6 -1
- package/dist/editor/services/aiService.js +4 -0
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.js +1 -1
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/ViewSelector.js +9 -4
- package/dist/editor/sidebar/ViewSelector.js.map +1 -1
- package/dist/editor/ui/Icons.d.ts +17 -1
- package/dist/editor/ui/Icons.js +23 -5
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/SimpleMenu.js +1 -1
- package/dist/editor/ui/SimpleMenu.js.map +1 -1
- package/dist/images/wizard-bg.png +0 -0
- package/dist/page-wizard/WizardBox.d.ts +8 -0
- package/dist/page-wizard/WizardBox.js +6 -0
- package/dist/page-wizard/WizardBox.js.map +1 -0
- package/dist/page-wizard/WizardBoxConnector.d.ts +3 -0
- package/dist/page-wizard/WizardBoxConnector.js +6 -0
- package/dist/page-wizard/WizardBoxConnector.js.map +1 -0
- package/dist/page-wizard/WizardSteps.js +63 -16
- package/dist/page-wizard/WizardSteps.js.map +1 -1
- package/dist/page-wizard/steps/CollectStep.js +16 -21
- package/dist/page-wizard/steps/CollectStep.js.map +1 -1
- package/dist/page-wizard/steps/ComponentTypesSelector.js +50 -45
- package/dist/page-wizard/steps/ComponentTypesSelector.js.map +1 -1
- package/dist/page-wizard/steps/CreatePageAndLayoutStep.js +21 -28
- package/dist/page-wizard/steps/CreatePageAndLayoutStep.js.map +1 -1
- package/dist/page-wizard/steps/usePageCreator.js +41 -12
- package/dist/page-wizard/steps/usePageCreator.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +144 -49
- package/images/wizard-bg.png +0 -0
- package/package.json +1 -1
- package/src/components/ActionButton.tsx +6 -8
- package/src/components/ui/button.tsx +2 -2
- package/src/config/config.tsx +47 -22
- package/src/editor/FieldListField.tsx +2 -2
- package/src/editor/Titlebar.tsx +2 -1
- package/src/editor/client/EditorClient.tsx +153 -8
- package/src/editor/client/editContext.ts +4 -2
- package/src/editor/client/itemsRepository.ts +1 -1
- package/src/editor/client/operations.ts +1 -1
- package/src/editor/control-center/About.tsx +342 -0
- package/src/editor/control-center/ControlCenterMenu.tsx +5 -0
- package/src/editor/control-center/Info.tsx +104 -0
- package/src/editor/control-center/QuotaInfo.tsx +171 -0
- package/src/editor/control-center/Status.tsx +108 -2
- package/src/editor/page-editor-chrome/FieldActionIndicator.tsx +20 -5
- package/src/editor/page-viewer/PageViewer.tsx +1 -1
- package/src/editor/services/aiService.ts +13 -1
- package/src/editor/sidebar/ComponentTree.tsx +1 -1
- package/src/editor/sidebar/ViewSelector.tsx +10 -11
- package/src/editor/ui/Icons.tsx +147 -26
- package/src/editor/ui/SimpleMenu.tsx +1 -1
- package/src/page-wizard/WizardBox.tsx +40 -0
- package/src/page-wizard/WizardBoxConnector.tsx +21 -0
- package/src/page-wizard/WizardSteps.tsx +134 -84
- package/src/page-wizard/steps/CollectStep.tsx +129 -67
- package/src/page-wizard/steps/ComponentTypesSelector.tsx +32 -11
- package/src/page-wizard/steps/CreatePageAndLayoutStep.tsx +47 -30
- package/src/page-wizard/steps/usePageCreator.ts +40 -14
- package/src/revision.ts +2 -2
- package/styles.css +11 -8
|
@@ -170,9 +170,9 @@ export default function FieldListField({
|
|
|
170
170
|
></SimpleIconButton>
|
|
171
171
|
)}
|
|
172
172
|
{executingAction && executingAction.state === "running" && (
|
|
173
|
-
<div className="ml-auto flex items-center gap-
|
|
173
|
+
<div className="ml-auto flex items-center gap-1.5 text-xs">
|
|
174
174
|
<i className="pi pi-spin pi-spinner flex items-center text-xs" />{" "}
|
|
175
|
-
{executingAction?.
|
|
175
|
+
{executingAction?.label}
|
|
176
176
|
</div>
|
|
177
177
|
)}
|
|
178
178
|
<OverlayPanel ref={generatorsOverlay} className="p-1">
|
package/src/editor/Titlebar.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { MenuIcon } from "lucide-react";
|
|
|
2
2
|
import { useEditContext } from "./client/editContext";
|
|
3
3
|
import { useEffect, useState, useRef } from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
|
+
import { Logo } from "./ui/Icons";
|
|
5
6
|
|
|
6
7
|
export function Titlebar() {
|
|
7
8
|
const editContext = useEditContext();
|
|
@@ -43,7 +44,7 @@ export function Titlebar() {
|
|
|
43
44
|
href="/sitecore/shell/sitecore/client/Applications/Launchpad"
|
|
44
45
|
className="glow-text flex items-center"
|
|
45
46
|
>
|
|
46
|
-
<
|
|
47
|
+
<Logo />
|
|
47
48
|
<span className="ml-2 font-mono">workbench</span>
|
|
48
49
|
</a>
|
|
49
50
|
</div>
|
|
@@ -121,20 +121,26 @@ import { usePageWizard } from "../../page-wizard/usePageWizard";
|
|
|
121
121
|
|
|
122
122
|
export type FieldAction = {
|
|
123
123
|
field: FieldDescriptor;
|
|
124
|
-
actionButton: FieldButton;
|
|
125
124
|
message?: string;
|
|
126
125
|
state: "running" | "success" | "error";
|
|
126
|
+
label?: string;
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
-
export type WindowSize = {
|
|
130
|
-
width: number;
|
|
131
|
-
height: number;
|
|
132
|
-
};
|
|
133
|
-
|
|
129
|
+
export type WindowSize = { width: number; height: number };
|
|
134
130
|
export type InsertingState = {
|
|
135
131
|
positionElement: Element;
|
|
136
132
|
positionAnchor: "left" | "right" | "top" | "bottom";
|
|
137
133
|
};
|
|
134
|
+
export type QuotaUsage = { tokens: number; images: number };
|
|
135
|
+
export type QuotaLimits = {
|
|
136
|
+
absoluteTokens: number;
|
|
137
|
+
dailyTokens: number;
|
|
138
|
+
monthlyTokens: number;
|
|
139
|
+
absoluteImages: number;
|
|
140
|
+
dailyImages: number;
|
|
141
|
+
monthlyImages: number;
|
|
142
|
+
};
|
|
143
|
+
export type QuotaInfo = { usage: QuotaUsage; limits: QuotaLimits };
|
|
138
144
|
|
|
139
145
|
export function EditorClient({
|
|
140
146
|
configuration,
|
|
@@ -284,7 +290,7 @@ export function EditorClient({
|
|
|
284
290
|
const [focusFieldComponentId, setFocusFieldComponentId] = useState<string>();
|
|
285
291
|
|
|
286
292
|
const [enableCompletions, setEnableCompletions] = useState(false);
|
|
287
|
-
|
|
293
|
+
const [quotaInfo, setQuotaInfo] = useState<QuotaInfo | null>(null);
|
|
288
294
|
const pageWizard = usePageWizard();
|
|
289
295
|
|
|
290
296
|
useEffect(() => {
|
|
@@ -390,6 +396,8 @@ export function EditorClient({
|
|
|
390
396
|
if (!event.data.startsWith("{")) return;
|
|
391
397
|
const message = JSON.parse(event.data);
|
|
392
398
|
|
|
399
|
+
console.log("message", message);
|
|
400
|
+
|
|
393
401
|
if (message.type === "active-sessions") {
|
|
394
402
|
setActiveSessions(() => {
|
|
395
403
|
return message.payload;
|
|
@@ -459,6 +467,69 @@ export function EditorClient({
|
|
|
459
467
|
});
|
|
460
468
|
}
|
|
461
469
|
|
|
470
|
+
if (message.type === "executing-field-action") {
|
|
471
|
+
setActiveFieldActions((x) => {
|
|
472
|
+
const payload = message.payload;
|
|
473
|
+
const fieldId = payload.fieldId;
|
|
474
|
+
const item = payload.item;
|
|
475
|
+
const status = payload.status;
|
|
476
|
+
const msg = payload.message;
|
|
477
|
+
const label = payload.label;
|
|
478
|
+
|
|
479
|
+
// Map backend status to FieldAction state
|
|
480
|
+
let state: "running" | "success" | "error";
|
|
481
|
+
switch (status?.toLowerCase()) {
|
|
482
|
+
case "completed":
|
|
483
|
+
case "success":
|
|
484
|
+
state = "success";
|
|
485
|
+
break;
|
|
486
|
+
case "failed":
|
|
487
|
+
case "error":
|
|
488
|
+
state = "error";
|
|
489
|
+
break;
|
|
490
|
+
default:
|
|
491
|
+
state = "running";
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Check if action already exists
|
|
496
|
+
const existingActionIndex = x.findIndex(
|
|
497
|
+
(action) =>
|
|
498
|
+
action.field.fieldId === fieldId &&
|
|
499
|
+
action.field.item.id === item.id &&
|
|
500
|
+
action.field.item.language === item.language &&
|
|
501
|
+
action.field.item.version === item.version,
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
if (existingActionIndex !== -1) {
|
|
505
|
+
// Update existing action
|
|
506
|
+
const newActions = [...x];
|
|
507
|
+
newActions[existingActionIndex]!.state = state;
|
|
508
|
+
newActions[existingActionIndex]!.message = msg;
|
|
509
|
+
return newActions;
|
|
510
|
+
} else {
|
|
511
|
+
// Insert new action
|
|
512
|
+
const fieldDescriptor: FieldDescriptor = {
|
|
513
|
+
fieldId: fieldId,
|
|
514
|
+
item: item,
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
const newAction: FieldAction = {
|
|
518
|
+
field: fieldDescriptor,
|
|
519
|
+
state,
|
|
520
|
+
message: msg,
|
|
521
|
+
label: label,
|
|
522
|
+
};
|
|
523
|
+
console.log(newAction);
|
|
524
|
+
return [...x, newAction];
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (message.type === "update-quota") {
|
|
530
|
+
setQuotaInfo(message.payload);
|
|
531
|
+
}
|
|
532
|
+
|
|
462
533
|
if (message.type === "edit-operation") {
|
|
463
534
|
const op = message.payload as EditOperation;
|
|
464
535
|
|
|
@@ -1432,6 +1503,73 @@ export function EditorClient({
|
|
|
1432
1503
|
router.push(url.toString(), { scroll: false });
|
|
1433
1504
|
}, []);
|
|
1434
1505
|
|
|
1506
|
+
// Quota checking functions
|
|
1507
|
+
const isQuotaExceeded = useCallback(() => {
|
|
1508
|
+
if (!quotaInfo) return false;
|
|
1509
|
+
|
|
1510
|
+
const { usage, limits } = quotaInfo;
|
|
1511
|
+
|
|
1512
|
+
// Check absolute limits
|
|
1513
|
+
if (limits.absoluteTokens > 0 && usage.tokens >= limits.absoluteTokens)
|
|
1514
|
+
return true;
|
|
1515
|
+
if (limits.absoluteImages > 0 && usage.images >= limits.absoluteImages)
|
|
1516
|
+
return true;
|
|
1517
|
+
|
|
1518
|
+
// For now, we're only checking absolute limits as daily/monthly would require server-side logic
|
|
1519
|
+
// You can extend this to check daily/monthly limits if the server provides that information
|
|
1520
|
+
|
|
1521
|
+
return false;
|
|
1522
|
+
}, [quotaInfo]);
|
|
1523
|
+
|
|
1524
|
+
const getQuotaWarningMessage = useCallback(() => {
|
|
1525
|
+
if (!quotaInfo) return null;
|
|
1526
|
+
|
|
1527
|
+
const { usage, limits } = quotaInfo;
|
|
1528
|
+
const warnings: string[] = [];
|
|
1529
|
+
|
|
1530
|
+
// Check tokens
|
|
1531
|
+
if (limits.absoluteTokens > 0) {
|
|
1532
|
+
const tokenPercentage = (usage.tokens / limits.absoluteTokens) * 100;
|
|
1533
|
+
if (tokenPercentage >= 100) {
|
|
1534
|
+
warnings.push(
|
|
1535
|
+
`Token limit exceeded (${usage.tokens}/${limits.absoluteTokens})`,
|
|
1536
|
+
);
|
|
1537
|
+
} else if (tokenPercentage >= 90) {
|
|
1538
|
+
warnings.push(
|
|
1539
|
+
`Token usage high: ${Math.round(tokenPercentage)}% (${usage.tokens}/${limits.absoluteTokens})`,
|
|
1540
|
+
);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
// Check images
|
|
1545
|
+
if (limits.absoluteImages > 0) {
|
|
1546
|
+
const imagePercentage = (usage.images / limits.absoluteImages) * 100;
|
|
1547
|
+
if (imagePercentage >= 100) {
|
|
1548
|
+
warnings.push(
|
|
1549
|
+
`Image limit exceeded (${usage.images}/${limits.absoluteImages})`,
|
|
1550
|
+
);
|
|
1551
|
+
} else if (imagePercentage >= 90) {
|
|
1552
|
+
warnings.push(
|
|
1553
|
+
`Image usage high: ${Math.round(imagePercentage)}% (${usage.images}/${limits.absoluteImages})`,
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
return warnings.length > 0 ? warnings.join(", ") : null;
|
|
1559
|
+
}, [quotaInfo]);
|
|
1560
|
+
|
|
1561
|
+
// Show warning when quota is exceeded
|
|
1562
|
+
useEffect(() => {
|
|
1563
|
+
const warningMessage = getQuotaWarningMessage();
|
|
1564
|
+
if (warningMessage) {
|
|
1565
|
+
const isExceeded = isQuotaExceeded();
|
|
1566
|
+
showErrorToast({
|
|
1567
|
+
summary: isExceeded ? "AI Quota Exceeded" : "AI Quota Warning",
|
|
1568
|
+
details: warningMessage,
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
}, [quotaInfo, getQuotaWarningMessage, isQuotaExceeded, showErrorToast]);
|
|
1572
|
+
|
|
1435
1573
|
const editContext = useMemo(() => {
|
|
1436
1574
|
return {
|
|
1437
1575
|
operations: operationsContext.ops,
|
|
@@ -1600,7 +1738,8 @@ export function EditorClient({
|
|
|
1600
1738
|
|
|
1601
1739
|
const op: FieldAction = {
|
|
1602
1740
|
field: fieldDescriptor,
|
|
1603
|
-
actionButton,
|
|
1741
|
+
// actionButton,
|
|
1742
|
+
label: actionButton.label,
|
|
1604
1743
|
state: "running",
|
|
1605
1744
|
};
|
|
1606
1745
|
const fieldItem = fieldDescriptor.item;
|
|
@@ -1807,6 +1946,9 @@ export function EditorClient({
|
|
|
1807
1946
|
setShowSuggestedEditsDiff,
|
|
1808
1947
|
enableCompletions,
|
|
1809
1948
|
setEnableCompletions,
|
|
1949
|
+
quotaInfo,
|
|
1950
|
+
isQuotaExceeded: isQuotaExceeded(),
|
|
1951
|
+
getQuotaWarningMessage,
|
|
1810
1952
|
isMobile,
|
|
1811
1953
|
openDialog,
|
|
1812
1954
|
pageWizard,
|
|
@@ -1883,6 +2025,9 @@ export function EditorClient({
|
|
|
1883
2025
|
setShowSuggestedEdits,
|
|
1884
2026
|
showSuggestedEditsDiff,
|
|
1885
2027
|
setShowSuggestedEditsDiff,
|
|
2028
|
+
quotaInfo,
|
|
2029
|
+
isQuotaExceeded,
|
|
2030
|
+
getQuotaWarningMessage,
|
|
1886
2031
|
isMobile,
|
|
1887
2032
|
openDialog,
|
|
1888
2033
|
pageWizard,
|
|
@@ -10,7 +10,7 @@ import React, {
|
|
|
10
10
|
import { ToastMessage } from "primereact/toast";
|
|
11
11
|
|
|
12
12
|
import { EditorConfiguration, EditorView } from "../../config/types";
|
|
13
|
-
import { FieldAction, InsertingState } from "./EditorClient";
|
|
13
|
+
import { FieldAction, InsertingState, QuotaInfo } from "./EditorClient";
|
|
14
14
|
import { MenuItem } from "primereact/menuitem";
|
|
15
15
|
import { Command, CommandData } from "../commands/commands";
|
|
16
16
|
import { ComponentDetails } from "../services/componentDesignerService";
|
|
@@ -303,7 +303,9 @@ export type EditContextType = {
|
|
|
303
303
|
|
|
304
304
|
enableCompletions: boolean;
|
|
305
305
|
setEnableCompletions: React.Dispatch<React.SetStateAction<boolean>>;
|
|
306
|
-
|
|
306
|
+
quotaInfo: QuotaInfo | null;
|
|
307
|
+
isQuotaExceeded: boolean;
|
|
308
|
+
getQuotaWarningMessage: () => string | null;
|
|
307
309
|
isMobile: boolean;
|
|
308
310
|
|
|
309
311
|
openDialog: OpenDialog;
|
|
@@ -387,7 +387,7 @@ export function getOperationsContext(
|
|
|
387
387
|
value,
|
|
388
388
|
rawValue,
|
|
389
389
|
);
|
|
390
|
-
editFieldImmediate({ field, value, rawValue, refresh });
|
|
390
|
+
return editFieldImmediate({ field, value, rawValue, refresh });
|
|
391
391
|
},
|
|
392
392
|
state.configuration.debounceFieldEditsInterval * 2,
|
|
393
393
|
{ trailing: true },
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useEditContext } from "../client/editContext";
|
|
3
|
+
import { version, buildDate } from "../../revision";
|
|
4
|
+
|
|
5
|
+
export function About() {
|
|
6
|
+
const editContext = useEditContext();
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className="max-h-full space-y-6 p-4">
|
|
10
|
+
<div className="space-y-4">
|
|
11
|
+
<h2 className="text-xl font-semibold text-gray-800">
|
|
12
|
+
About Alpaca Editor
|
|
13
|
+
</h2>
|
|
14
|
+
{/* Application Information */}
|
|
15
|
+
<div className="rounded-lg border border-gray-200 bg-white p-4">
|
|
16
|
+
<h3 className="mb-3 text-lg font-medium text-gray-700">
|
|
17
|
+
Application Information
|
|
18
|
+
</h3>
|
|
19
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
20
|
+
<div>
|
|
21
|
+
<label className="text-sm font-medium text-gray-500">
|
|
22
|
+
Product Name
|
|
23
|
+
</label>
|
|
24
|
+
<p className="text-gray-900">Alpaca Editor</p>
|
|
25
|
+
</div>
|
|
26
|
+
<div>
|
|
27
|
+
<label className="text-sm font-medium text-gray-500">
|
|
28
|
+
Version
|
|
29
|
+
</label>
|
|
30
|
+
<p className="text-gray-900">{version}</p>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div>
|
|
34
|
+
<label className="text-sm font-medium text-gray-500">
|
|
35
|
+
Build Date
|
|
36
|
+
</label>
|
|
37
|
+
<p className="text-gray-900">{buildDate}</p>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
{/* License Information */}{" "}
|
|
42
|
+
<div className="rounded-lg border border-gray-200 bg-white p-4">
|
|
43
|
+
{" "}
|
|
44
|
+
<h3 className="mb-3 text-lg font-medium text-gray-700">
|
|
45
|
+
{" "}
|
|
46
|
+
License Information{" "}
|
|
47
|
+
</h3>{" "}
|
|
48
|
+
<div className="space-y-4">
|
|
49
|
+
{" "}
|
|
50
|
+
<div>
|
|
51
|
+
{" "}
|
|
52
|
+
<label className="text-sm font-medium text-gray-500">
|
|
53
|
+
{" "}
|
|
54
|
+
Copyright{" "}
|
|
55
|
+
</label>{" "}
|
|
56
|
+
<p className="text-gray-900">© 2025 Canvas Reply GmbH</p>{" "}
|
|
57
|
+
</div>{" "}
|
|
58
|
+
<div>
|
|
59
|
+
{" "}
|
|
60
|
+
<label className="text-sm font-medium text-gray-500">
|
|
61
|
+
{" "}
|
|
62
|
+
License{" "}
|
|
63
|
+
</label>{" "}
|
|
64
|
+
<p className="text-gray-900">
|
|
65
|
+
{" "}
|
|
66
|
+
All rights reserved. Please contact Canvas Reply GmbH for
|
|
67
|
+
licensing information.{" "}
|
|
68
|
+
</p>{" "}
|
|
69
|
+
</div>{" "}
|
|
70
|
+
</div>{" "}
|
|
71
|
+
</div>
|
|
72
|
+
{/* Third-Party Licenses */}{" "}
|
|
73
|
+
<div className="rounded-lg border border-gray-200 bg-white p-4">
|
|
74
|
+
{" "}
|
|
75
|
+
<h3 className="mb-3 text-lg font-medium text-gray-700">
|
|
76
|
+
{" "}
|
|
77
|
+
Third-Party Components{" "}
|
|
78
|
+
</h3>{" "}
|
|
79
|
+
<div className="max-h-96 space-y-3 overflow-y-auto">
|
|
80
|
+
{" "}
|
|
81
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
82
|
+
{" "}
|
|
83
|
+
<div className="mb-2 flex items-center justify-between">
|
|
84
|
+
{" "}
|
|
85
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
86
|
+
React
|
|
87
|
+
</h4>{" "}
|
|
88
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
89
|
+
</div>{" "}
|
|
90
|
+
<p className="text-xs text-gray-600">
|
|
91
|
+
{" "}
|
|
92
|
+
A JavaScript library for building user interfaces{" "}
|
|
93
|
+
</p>{" "}
|
|
94
|
+
</div>{" "}
|
|
95
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
96
|
+
{" "}
|
|
97
|
+
<div className="mb-2 flex items-center justify-between">
|
|
98
|
+
{" "}
|
|
99
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
100
|
+
Next.js
|
|
101
|
+
</h4>{" "}
|
|
102
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
103
|
+
</div>{" "}
|
|
104
|
+
<p className="text-xs text-gray-600">
|
|
105
|
+
{" "}
|
|
106
|
+
The React Framework for Production{" "}
|
|
107
|
+
</p>{" "}
|
|
108
|
+
</div>{" "}
|
|
109
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
110
|
+
{" "}
|
|
111
|
+
<div className="mb-2 flex items-center justify-between">
|
|
112
|
+
{" "}
|
|
113
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
114
|
+
TypeScript
|
|
115
|
+
</h4>{" "}
|
|
116
|
+
<span className="text-xs text-gray-500">
|
|
117
|
+
Apache 2.0 License
|
|
118
|
+
</span>{" "}
|
|
119
|
+
</div>{" "}
|
|
120
|
+
<p className="text-xs text-gray-600">
|
|
121
|
+
{" "}
|
|
122
|
+
TypeScript is a language for application scale JavaScript
|
|
123
|
+
development{" "}
|
|
124
|
+
</p>{" "}
|
|
125
|
+
</div>{" "}
|
|
126
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
127
|
+
{" "}
|
|
128
|
+
<div className="mb-2 flex items-center justify-between">
|
|
129
|
+
{" "}
|
|
130
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
131
|
+
Tailwind CSS
|
|
132
|
+
</h4>{" "}
|
|
133
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
134
|
+
</div>{" "}
|
|
135
|
+
<p className="text-xs text-gray-600">
|
|
136
|
+
{" "}
|
|
137
|
+
A utility-first CSS framework for rapidly building custom
|
|
138
|
+
designs{" "}
|
|
139
|
+
</p>{" "}
|
|
140
|
+
</div>{" "}
|
|
141
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
142
|
+
{" "}
|
|
143
|
+
<div className="mb-2 flex items-center justify-between">
|
|
144
|
+
{" "}
|
|
145
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
146
|
+
PrimeReact
|
|
147
|
+
</h4>{" "}
|
|
148
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
149
|
+
</div>{" "}
|
|
150
|
+
<p className="text-xs text-gray-600">
|
|
151
|
+
{" "}
|
|
152
|
+
React UI Component Library with rich set of components{" "}
|
|
153
|
+
</p>{" "}
|
|
154
|
+
</div>{" "}
|
|
155
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
156
|
+
{" "}
|
|
157
|
+
<div className="mb-2 flex items-center justify-between">
|
|
158
|
+
{" "}
|
|
159
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
160
|
+
Lucide React
|
|
161
|
+
</h4>{" "}
|
|
162
|
+
<span className="text-xs text-gray-500">ISC License</span>{" "}
|
|
163
|
+
</div>{" "}
|
|
164
|
+
<p className="text-xs text-gray-600">
|
|
165
|
+
{" "}
|
|
166
|
+
Beautiful & consistent icon toolkit made by the community{" "}
|
|
167
|
+
</p>{" "}
|
|
168
|
+
</div>{" "}
|
|
169
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
170
|
+
{" "}
|
|
171
|
+
<div className="mb-2 flex items-center justify-between">
|
|
172
|
+
{" "}
|
|
173
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
174
|
+
Radix UI
|
|
175
|
+
</h4>{" "}
|
|
176
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
177
|
+
</div>{" "}
|
|
178
|
+
<p className="text-xs text-gray-600">
|
|
179
|
+
{" "}
|
|
180
|
+
Low-level UI primitives for React with accessibility
|
|
181
|
+
built-in{" "}
|
|
182
|
+
</p>{" "}
|
|
183
|
+
</div>{" "}
|
|
184
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
185
|
+
{" "}
|
|
186
|
+
<div className="mb-2 flex items-center justify-between">
|
|
187
|
+
{" "}
|
|
188
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
189
|
+
Axios
|
|
190
|
+
</h4>{" "}
|
|
191
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
192
|
+
</div>{" "}
|
|
193
|
+
<p className="text-xs text-gray-600">
|
|
194
|
+
{" "}
|
|
195
|
+
Promise based HTTP client for the browser and node.js{" "}
|
|
196
|
+
</p>{" "}
|
|
197
|
+
</div>{" "}
|
|
198
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
199
|
+
{" "}
|
|
200
|
+
<div className="mb-2 flex items-center justify-between">
|
|
201
|
+
{" "}
|
|
202
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
203
|
+
Quill
|
|
204
|
+
</h4>{" "}
|
|
205
|
+
<span className="text-xs text-gray-500">
|
|
206
|
+
BSD 3-Clause License
|
|
207
|
+
</span>{" "}
|
|
208
|
+
</div>{" "}
|
|
209
|
+
<p className="text-xs text-gray-600">
|
|
210
|
+
{" "}
|
|
211
|
+
Modern WYSIWYG editor built for compatibility and
|
|
212
|
+
extensibility{" "}
|
|
213
|
+
</p>{" "}
|
|
214
|
+
</div>{" "}
|
|
215
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
216
|
+
{" "}
|
|
217
|
+
<div className="mb-2 flex items-center justify-between">
|
|
218
|
+
{" "}
|
|
219
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
220
|
+
React Inspector
|
|
221
|
+
</h4>{" "}
|
|
222
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
223
|
+
</div>{" "}
|
|
224
|
+
<p className="text-xs text-gray-600">
|
|
225
|
+
{" "}
|
|
226
|
+
Power of Browser DevTools inspectors right inside your React
|
|
227
|
+
app{" "}
|
|
228
|
+
</p>{" "}
|
|
229
|
+
</div>{" "}
|
|
230
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
231
|
+
{" "}
|
|
232
|
+
<div className="mb-2 flex items-center justify-between">
|
|
233
|
+
{" "}
|
|
234
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
235
|
+
Allotment
|
|
236
|
+
</h4>{" "}
|
|
237
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
238
|
+
</div>{" "}
|
|
239
|
+
<p className="text-xs text-gray-600">
|
|
240
|
+
{" "}
|
|
241
|
+
React split-pane component with support for multiple
|
|
242
|
+
layouts{" "}
|
|
243
|
+
</p>{" "}
|
|
244
|
+
</div>{" "}
|
|
245
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
246
|
+
{" "}
|
|
247
|
+
<div className="mb-2 flex items-center justify-between">
|
|
248
|
+
{" "}
|
|
249
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
250
|
+
Lodash
|
|
251
|
+
</h4>{" "}
|
|
252
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
253
|
+
</div>{" "}
|
|
254
|
+
<p className="text-xs text-gray-600">
|
|
255
|
+
{" "}
|
|
256
|
+
A modern JavaScript utility library delivering modularity,
|
|
257
|
+
performance & extras{" "}
|
|
258
|
+
</p>{" "}
|
|
259
|
+
</div>{" "}
|
|
260
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
261
|
+
{" "}
|
|
262
|
+
<div className="mb-2 flex items-center justify-between">
|
|
263
|
+
{" "}
|
|
264
|
+
<h4 className="text-sm font-medium text-gray-700">clsx</h4>{" "}
|
|
265
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
266
|
+
</div>{" "}
|
|
267
|
+
<p className="text-xs text-gray-600">
|
|
268
|
+
{" "}
|
|
269
|
+
A tiny utility for constructing className strings
|
|
270
|
+
conditionally{" "}
|
|
271
|
+
</p>{" "}
|
|
272
|
+
</div>{" "}
|
|
273
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
274
|
+
{" "}
|
|
275
|
+
<div className="mb-2 flex items-center justify-between">
|
|
276
|
+
{" "}
|
|
277
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
278
|
+
PostCSS
|
|
279
|
+
</h4>{" "}
|
|
280
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
281
|
+
</div>{" "}
|
|
282
|
+
<p className="text-xs text-gray-600">
|
|
283
|
+
{" "}
|
|
284
|
+
Tool for transforming CSS with JavaScript{" "}
|
|
285
|
+
</p>{" "}
|
|
286
|
+
</div>{" "}
|
|
287
|
+
<div className="rounded-lg bg-gray-50 p-3">
|
|
288
|
+
{" "}
|
|
289
|
+
<div className="mb-2 flex items-center justify-between">
|
|
290
|
+
{" "}
|
|
291
|
+
<h4 className="text-sm font-medium text-gray-700">
|
|
292
|
+
Universal Cookie
|
|
293
|
+
</h4>{" "}
|
|
294
|
+
<span className="text-xs text-gray-500">MIT License</span>{" "}
|
|
295
|
+
</div>{" "}
|
|
296
|
+
<p className="text-xs text-gray-600">
|
|
297
|
+
{" "}
|
|
298
|
+
Universal cookies for JavaScript{" "}
|
|
299
|
+
</p>{" "}
|
|
300
|
+
</div>{" "}
|
|
301
|
+
</div>{" "}
|
|
302
|
+
</div>
|
|
303
|
+
{/* Contact Information */}
|
|
304
|
+
<div className="rounded-lg border border-gray-200 bg-white p-4">
|
|
305
|
+
<h3 className="mb-3 text-lg font-medium text-gray-700">
|
|
306
|
+
Contact & Support
|
|
307
|
+
</h3>
|
|
308
|
+
<div className="space-y-3">
|
|
309
|
+
<div>
|
|
310
|
+
<label className="text-sm font-medium text-gray-500">
|
|
311
|
+
Documentation
|
|
312
|
+
</label>
|
|
313
|
+
<p className="text-gray-900">
|
|
314
|
+
<a
|
|
315
|
+
href="#"
|
|
316
|
+
className="text-blue-600 underline hover:text-blue-800"
|
|
317
|
+
onClick={(e) => e.preventDefault()}
|
|
318
|
+
>
|
|
319
|
+
View Documentation
|
|
320
|
+
</a>
|
|
321
|
+
</p>
|
|
322
|
+
</div>
|
|
323
|
+
<div>
|
|
324
|
+
<label className="text-sm font-medium text-gray-500">
|
|
325
|
+
Support
|
|
326
|
+
</label>
|
|
327
|
+
<p className="text-gray-900">
|
|
328
|
+
<a
|
|
329
|
+
href="#"
|
|
330
|
+
className="text-blue-600 underline hover:text-blue-800"
|
|
331
|
+
onClick={(e) => e.preventDefault()}
|
|
332
|
+
>
|
|
333
|
+
Contact Support
|
|
334
|
+
</a>
|
|
335
|
+
</p>
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
@@ -50,6 +50,11 @@ export function ControlCenterMenu() {
|
|
|
50
50
|
const item = groups
|
|
51
51
|
?.flatMap((x) => x.panels)
|
|
52
52
|
?.find((item) => item.id === activeItemKey);
|
|
53
|
+
|
|
54
|
+
if (!item) {
|
|
55
|
+
setActiveItemKey(groups?.[0]?.panels?.[0]?.id || null);
|
|
56
|
+
}
|
|
57
|
+
|
|
53
58
|
if (item) {
|
|
54
59
|
editContext?.setCenterPanelView(item.content);
|
|
55
60
|
}
|