@webiny/app-admin-ui 0.0.0-unstable.a4f3e4ea8b → 0.0.0-unstable.a85ef555b2
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/Breadcrumbs/Breadcrumbs.d.ts +14 -0
- package/Breadcrumbs/Breadcrumbs.js +74 -0
- package/Breadcrumbs/Breadcrumbs.js.map +1 -0
- package/CommandPalette/CommandPalette.d.ts +2 -2
- package/CommandPalette/CommandPalette.js +106 -75
- package/CommandPalette/CommandPalette.js.map +1 -1
- package/CommandPalette/components/AiModeBadge.d.ts +3 -0
- package/CommandPalette/components/AiModeBadge.js +11 -0
- package/CommandPalette/components/AiModeBadge.js.map +1 -0
- package/CommandPalette/components/AiSuggestions.d.ts +9 -0
- package/CommandPalette/components/AiSuggestions.js +32 -0
- package/CommandPalette/components/AiSuggestions.js.map +1 -0
- package/CommandPalette/components/AiTurn.d.ts +11 -0
- package/CommandPalette/components/AiTurn.js +61 -0
- package/CommandPalette/components/AiTurn.js.map +1 -0
- package/CommandPalette/components/AnswerSkeleton.d.ts +6 -0
- package/CommandPalette/components/AnswerSkeleton.js +20 -0
- package/CommandPalette/components/AnswerSkeleton.js.map +1 -0
- package/CommandPalette/components/ApprovalPlan.d.ts +16 -0
- package/CommandPalette/components/ApprovalPlan.js +56 -0
- package/CommandPalette/components/ApprovalPlan.js.map +1 -0
- package/CommandPalette/components/CommandItemRow.js +4 -2
- package/CommandPalette/components/CommandItemRow.js.map +1 -1
- package/CommandPalette/components/NoResults.d.ts +13 -0
- package/CommandPalette/components/NoResults.js +33 -0
- package/CommandPalette/components/NoResults.js.map +1 -0
- package/CommandPalette/components/PaletteFooter.d.ts +13 -0
- package/CommandPalette/components/PaletteFooter.js +18 -0
- package/CommandPalette/components/PaletteFooter.js.map +1 -0
- package/CommandPalette/components/ToolChip.d.ts +7 -0
- package/CommandPalette/components/ToolChip.js +32 -0
- package/CommandPalette/components/ToolChip.js.map +1 -0
- package/CommandPalette/components/index.d.ts +13 -5
- package/CommandPalette/components/index.js +13 -5
- package/CommandPalette/modes/PaletteMode.d.ts +73 -0
- package/CommandPalette/modes/PaletteMode.js +0 -0
- package/CommandPalette/modes/createAiMode.d.ts +13 -0
- package/CommandPalette/modes/createAiMode.js +80 -0
- package/CommandPalette/modes/createAiMode.js.map +1 -0
- package/CommandPalette/modes/index.d.ts +2 -0
- package/CommandPalette/modes/index.js +1 -0
- package/CommandPalette/usePaletteHotkeys.d.ts +16 -0
- package/CommandPalette/usePaletteHotkeys.js +38 -0
- package/CommandPalette/usePaletteHotkeys.js.map +1 -0
- package/Dashboard/Welcome.d.ts +4 -1
- package/Dashboard/Welcome.js +111 -24
- package/Dashboard/Welcome.js.map +1 -1
- package/Dashboard/components/DashboardToolbar.d.ts +11 -0
- package/Dashboard/components/DashboardToolbar.js +48 -0
- package/Dashboard/components/DashboardToolbar.js.map +1 -0
- package/Dashboard/components/addWidgetDrawer/AddToColumnMenu.d.ts +10 -0
- package/Dashboard/components/addWidgetDrawer/AddToColumnMenu.js +30 -0
- package/Dashboard/components/addWidgetDrawer/AddToColumnMenu.js.map +1 -0
- package/Dashboard/components/addWidgetDrawer/AddWidgetDrawer.d.ts +12 -0
- package/Dashboard/components/addWidgetDrawer/AddWidgetDrawer.js +61 -0
- package/Dashboard/components/addWidgetDrawer/AddWidgetDrawer.js.map +1 -0
- package/Dashboard/components/addWidgetDrawer/DrawerWidgetRow.d.ts +10 -0
- package/Dashboard/components/addWidgetDrawer/DrawerWidgetRow.js +38 -0
- package/Dashboard/components/addWidgetDrawer/DrawerWidgetRow.js.map +1 -0
- package/Dashboard/components/addWidgetDrawer/WidgetPreviewFrame.d.ts +7 -0
- package/Dashboard/components/addWidgetDrawer/WidgetPreviewFrame.js +44 -0
- package/Dashboard/components/addWidgetDrawer/WidgetPreviewFrame.js.map +1 -0
- package/Dashboard/components/addWidgetDrawer/WidgetSketch.d.ts +4 -0
- package/Dashboard/components/addWidgetDrawer/WidgetSketch.js +20 -0
- package/Dashboard/components/addWidgetDrawer/WidgetSketch.js.map +1 -0
- package/Dashboard/components/addWidgetDrawer/WidgetTabContent.d.ts +14 -0
- package/Dashboard/components/addWidgetDrawer/WidgetTabContent.js +76 -0
- package/Dashboard/components/addWidgetDrawer/WidgetTabContent.js.map +1 -0
- package/Dashboard/components/addWidgetDrawer/types.d.ts +10 -0
- package/Dashboard/components/addWidgetDrawer/types.js +0 -0
- package/Dashboard/components/dnd/ColumnCountControl.d.ts +9 -0
- package/Dashboard/components/dnd/ColumnCountControl.js +52 -0
- package/Dashboard/components/dnd/ColumnCountControl.js.map +1 -0
- package/Dashboard/components/dnd/ColumnEmptyState.d.ts +10 -0
- package/Dashboard/components/dnd/ColumnEmptyState.js +52 -0
- package/Dashboard/components/dnd/ColumnEmptyState.js.map +1 -0
- package/Dashboard/components/dnd/DashboardDragLayer.d.ts +6 -0
- package/Dashboard/components/dnd/DashboardDragLayer.js +28 -0
- package/Dashboard/components/dnd/DashboardDragLayer.js.map +1 -0
- package/Dashboard/components/dnd/DashboardWidgetCard.d.ts +13 -0
- package/Dashboard/components/dnd/DashboardWidgetCard.js +59 -0
- package/Dashboard/components/dnd/DashboardWidgetCard.js.map +1 -0
- package/Dashboard/components/dnd/DashboardWidgetColumn.d.ts +19 -0
- package/Dashboard/components/dnd/DashboardWidgetColumn.js +72 -0
- package/Dashboard/components/dnd/DashboardWidgetColumn.js.map +1 -0
- package/Dashboard/components/dnd/WidgetDropIndicator.d.ts +11 -0
- package/Dashboard/components/dnd/WidgetDropIndicator.js +29 -0
- package/Dashboard/components/dnd/WidgetDropIndicator.js.map +1 -0
- package/Dashboard/components/dnd/WidgetSlot.d.ts +6 -0
- package/Dashboard/components/dnd/WidgetSlot.js +9 -0
- package/Dashboard/components/dnd/WidgetSlot.js.map +1 -0
- package/Dashboard/components/dnd/dragItem.d.ts +6 -0
- package/Dashboard/components/dnd/dragItem.js +4 -0
- package/Dashboard/components/dnd/dragItem.js.map +1 -0
- package/Dashboard/components/dnd/useWidgetHosts.d.ts +1 -0
- package/Dashboard/components/dnd/useWidgetHosts.js +16 -0
- package/Dashboard/components/dnd/useWidgetHosts.js.map +1 -0
- package/Dashboard/components/layout/EditableColumns.d.ts +13 -0
- package/Dashboard/components/layout/EditableColumns.js +25 -0
- package/Dashboard/components/layout/EditableColumns.js.map +1 -0
- package/Dashboard/components/layout/StaticColumns.d.ts +8 -0
- package/Dashboard/components/layout/StaticColumns.js +20 -0
- package/Dashboard/components/layout/StaticColumns.js.map +1 -0
- package/Dashboard/components/layout/collapseColumns.d.ts +1 -0
- package/Dashboard/components/layout/collapseColumns.js +16 -0
- package/Dashboard/components/layout/collapseColumns.js.map +1 -0
- package/Dashboard/components/layout/layoutConstants.d.ts +2 -0
- package/Dashboard/components/layout/layoutConstants.js +5 -0
- package/Dashboard/components/layout/layoutConstants.js.map +1 -0
- package/Dashboard/components/layout/useColumnsThatFit.d.ts +6 -0
- package/Dashboard/components/layout/useColumnsThatFit.js +30 -0
- package/Dashboard/components/layout/useColumnsThatFit.js.map +1 -0
- package/Dashboard/components/layout/useWidgetPortals.d.ts +5 -0
- package/Dashboard/components/layout/useWidgetPortals.js +26 -0
- package/Dashboard/components/layout/useWidgetPortals.js.map +1 -0
- package/Dashboard/dashboardLayout/loadLayout/FetchDashboardLayoutUseCase.d.ts +12 -0
- package/Dashboard/dashboardLayout/loadLayout/FetchDashboardLayoutUseCase.js +19 -0
- package/Dashboard/dashboardLayout/loadLayout/FetchDashboardLayoutUseCase.js.map +1 -0
- package/Dashboard/dashboardLayout/loadLayout/GetCachedDashboardLayoutUseCase.d.ts +12 -0
- package/Dashboard/dashboardLayout/loadLayout/GetCachedDashboardLayoutUseCase.js +19 -0
- package/Dashboard/dashboardLayout/loadLayout/GetCachedDashboardLayoutUseCase.js.map +1 -0
- package/Dashboard/dashboardLayout/loadLayout/abstractions.d.ts +15 -0
- package/Dashboard/dashboardLayout/loadLayout/abstractions.js +6 -0
- package/Dashboard/dashboardLayout/loadLayout/abstractions.js.map +1 -0
- package/Dashboard/dashboardLayout/loadLayout/feature.d.ts +1 -0
- package/Dashboard/dashboardLayout/loadLayout/feature.js +13 -0
- package/Dashboard/dashboardLayout/loadLayout/feature.js.map +1 -0
- package/Dashboard/dashboardLayout/presenter/DashboardLayoutPresenter.d.ts +56 -0
- package/Dashboard/dashboardLayout/presenter/DashboardLayoutPresenter.js +308 -0
- package/Dashboard/dashboardLayout/presenter/DashboardLayoutPresenter.js.map +1 -0
- package/Dashboard/dashboardLayout/presenter/abstractions.d.ts +46 -0
- package/Dashboard/dashboardLayout/presenter/abstractions.js +5 -0
- package/Dashboard/dashboardLayout/presenter/abstractions.js.map +1 -0
- package/Dashboard/dashboardLayout/presenter/feature.d.ts +3 -0
- package/Dashboard/dashboardLayout/presenter/feature.js +23 -0
- package/Dashboard/dashboardLayout/presenter/feature.js.map +1 -0
- package/Dashboard/dashboardLayout/presenter/useDashboardLayoutPresenter.d.ts +1 -0
- package/Dashboard/dashboardLayout/presenter/useDashboardLayoutPresenter.js +6 -0
- package/Dashboard/dashboardLayout/presenter/useDashboardLayoutPresenter.js.map +1 -0
- package/Dashboard/dashboardLayout/repository/DashboardLayoutGateway.d.ts +13 -0
- package/Dashboard/dashboardLayout/repository/DashboardLayoutGateway.js +67 -0
- package/Dashboard/dashboardLayout/repository/DashboardLayoutGateway.js.map +1 -0
- package/Dashboard/dashboardLayout/repository/DashboardLayoutRepository.d.ts +20 -0
- package/Dashboard/dashboardLayout/repository/DashboardLayoutRepository.js +49 -0
- package/Dashboard/dashboardLayout/repository/DashboardLayoutRepository.js.map +1 -0
- package/Dashboard/dashboardLayout/repository/abstractions.d.ts +25 -0
- package/Dashboard/dashboardLayout/repository/abstractions.js +6 -0
- package/Dashboard/dashboardLayout/repository/abstractions.js.map +1 -0
- package/Dashboard/dashboardLayout/repository/feature.d.ts +1 -0
- package/Dashboard/dashboardLayout/repository/feature.js +13 -0
- package/Dashboard/dashboardLayout/repository/feature.js.map +1 -0
- package/Dashboard/dashboardLayout/saveLayout/SaveDashboardLayoutUseCase.d.ts +12 -0
- package/Dashboard/dashboardLayout/saveLayout/SaveDashboardLayoutUseCase.js +19 -0
- package/Dashboard/dashboardLayout/saveLayout/SaveDashboardLayoutUseCase.js.map +1 -0
- package/Dashboard/dashboardLayout/saveLayout/abstractions.d.ts +8 -0
- package/Dashboard/dashboardLayout/saveLayout/abstractions.js +5 -0
- package/Dashboard/dashboardLayout/saveLayout/abstractions.js.map +1 -0
- package/Dashboard/dashboardLayout/saveLayout/feature.d.ts +1 -0
- package/Dashboard/dashboardLayout/saveLayout/feature.js +11 -0
- package/Dashboard/dashboardLayout/saveLayout/feature.js.map +1 -0
- package/Dashboard/dashboardLayout/toColumnIndex.d.ts +1 -0
- package/Dashboard/dashboardLayout/toColumnIndex.js +7 -0
- package/Dashboard/dashboardLayout/toColumnIndex.js.map +1 -0
- package/Dashboard/dashboardLayout/types.d.ts +15 -0
- package/Dashboard/dashboardLayout/types.js +6 -0
- package/Dashboard/dashboardLayout/types.js.map +1 -0
- package/Layout.js +7 -5
- package/Layout.js.map +1 -1
- package/index.js +15 -4
- package/index.js.map +1 -1
- package/package.json +13 -7
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Skeleton } from "@webiny/admin-ui";
|
|
3
|
+
const AnswerSkeleton = ()=>/*#__PURE__*/ react.createElement("div", {
|
|
4
|
+
className: "flex flex-col gap-xs"
|
|
5
|
+
}, /*#__PURE__*/ react.createElement(Skeleton, {
|
|
6
|
+
type: "text",
|
|
7
|
+
size: "xs",
|
|
8
|
+
className: "w-[78%]"
|
|
9
|
+
}), /*#__PURE__*/ react.createElement(Skeleton, {
|
|
10
|
+
type: "text",
|
|
11
|
+
size: "xs",
|
|
12
|
+
className: "w-[92%]"
|
|
13
|
+
}), /*#__PURE__*/ react.createElement(Skeleton, {
|
|
14
|
+
type: "text",
|
|
15
|
+
size: "xs",
|
|
16
|
+
className: "w-[54%]"
|
|
17
|
+
}));
|
|
18
|
+
export { AnswerSkeleton };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=AnswerSkeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette/components/AnswerSkeleton.js","sources":["../../../src/CommandPalette/components/AnswerSkeleton.tsx"],"sourcesContent":["import React from \"react\";\nimport { Skeleton } from \"@webiny/admin-ui\";\n\n/**\n * Stands in for the answer while the request is in flight. Staggered widths read as prose rather\n * than as a progress bar, which is honest: we cannot show real progress without streaming.\n */\nexport const AnswerSkeleton = () => (\n <div className=\"flex flex-col gap-xs\">\n <Skeleton type=\"text\" size=\"xs\" className=\"w-[78%]\" />\n <Skeleton type=\"text\" size=\"xs\" className=\"w-[92%]\" />\n <Skeleton type=\"text\" size=\"xs\" className=\"w-[54%]\" />\n </div>\n);\n"],"names":["AnswerSkeleton","Skeleton"],"mappings":";;AAOO,MAAMA,iBAAiB,kBAC1B,oBAAC;QAAI,WAAU;qBACX,oBAACC,UAAQA;QAAC,MAAK;QAAO,MAAK;QAAK,WAAU;sBAC1C,oBAACA,UAAQA;QAAC,MAAK;QAAO,MAAK;QAAK,WAAU;sBAC1C,oBAACA,UAAQA;QAAC,MAAK;QAAO,MAAK;QAAK,WAAU"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { AdminAssistantPendingApproval } from "@webiny/app-admin";
|
|
3
|
+
export interface ApprovalPlanProps {
|
|
4
|
+
approvals: AdminAssistantPendingApproval[];
|
|
5
|
+
busy: boolean;
|
|
6
|
+
onApprove: () => void;
|
|
7
|
+
onReject: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The confirm gate for a proposed change.
|
|
11
|
+
*
|
|
12
|
+
* Arguments are shown as raw JSON on purpose. A prose summary would be the assistant describing its
|
|
13
|
+
* own request — and the assistant is exactly what is not yet trusted here. What the user approves has
|
|
14
|
+
* to be what actually runs.
|
|
15
|
+
*/
|
|
16
|
+
export declare const ApprovalPlan: ({ approvals, busy, onApprove, onReject }: ApprovalPlanProps) => React.JSX.Element | null;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Button, Icon, Text, cn } from "@webiny/admin-ui";
|
|
3
|
+
import { ReactComponent } from "@webiny/icons/bolt.svg";
|
|
4
|
+
import { ReactComponent as warning_svg_ReactComponent } from "@webiny/icons/warning.svg";
|
|
5
|
+
const ApprovalPlan = ({ approvals, busy, onApprove, onReject })=>{
|
|
6
|
+
if (0 === approvals.length) return null;
|
|
7
|
+
const destructive = approvals.some((approval)=>approval.destructive);
|
|
8
|
+
let heading = `Approve ${approvals.length} changes`;
|
|
9
|
+
if (1 === approvals.length) heading = `Approve: ${approvals[0].title ?? approvals[0].toolName}`;
|
|
10
|
+
return /*#__PURE__*/ react.createElement("div", {
|
|
11
|
+
className: cn("mt-sm overflow-hidden rounded-md border border-neutral-dimmed", destructive ? "bg-destructive-subtle" : "bg-warning-subtle")
|
|
12
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
13
|
+
className: "flex items-center gap-sm border-b border-neutral-dimmed px-sm py-xs-plus"
|
|
14
|
+
}, /*#__PURE__*/ react.createElement(Icon, {
|
|
15
|
+
icon: destructive ? /*#__PURE__*/ react.createElement(warning_svg_ReactComponent, null) : /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
16
|
+
size: "sm",
|
|
17
|
+
label: "",
|
|
18
|
+
color: "inherit",
|
|
19
|
+
className: destructive ? "text-destructive-primary" : void 0
|
|
20
|
+
}), /*#__PURE__*/ react.createElement(Text, {
|
|
21
|
+
size: "sm",
|
|
22
|
+
className: "font-semibold text-neutral-primary"
|
|
23
|
+
}, heading), destructive ? /*#__PURE__*/ react.createElement(Text, {
|
|
24
|
+
size: "sm",
|
|
25
|
+
className: "ml-auto text-destructive-primary"
|
|
26
|
+
}, "Cannot be undone") : null), /*#__PURE__*/ react.createElement("div", {
|
|
27
|
+
className: "bg-neutral-base px-sm py-xs-plus"
|
|
28
|
+
}, approvals.map((approval)=>/*#__PURE__*/ react.createElement("div", {
|
|
29
|
+
key: approval.approvalId,
|
|
30
|
+
className: "mb-xs"
|
|
31
|
+
}, /*#__PURE__*/ react.createElement(Text, {
|
|
32
|
+
as: "div",
|
|
33
|
+
size: "sm",
|
|
34
|
+
className: "font-mono text-neutral-strong"
|
|
35
|
+
}, approval.toolName), /*#__PURE__*/ react.createElement("pre", {
|
|
36
|
+
className: "mt-xxs overflow-x-auto rounded bg-neutral-subtle p-sm text-xs text-neutral-strong"
|
|
37
|
+
}, JSON.stringify(approval.input, null, 2)))), /*#__PURE__*/ react.createElement("div", {
|
|
38
|
+
className: "mt-sm flex items-center gap-sm"
|
|
39
|
+
}, /*#__PURE__*/ react.createElement(Button, {
|
|
40
|
+
variant: "primary",
|
|
41
|
+
text: "Run",
|
|
42
|
+
disabled: busy,
|
|
43
|
+
onClick: onApprove
|
|
44
|
+
}), /*#__PURE__*/ react.createElement(Button, {
|
|
45
|
+
variant: "secondary",
|
|
46
|
+
text: "Reject",
|
|
47
|
+
disabled: busy,
|
|
48
|
+
onClick: onReject
|
|
49
|
+
}), /*#__PURE__*/ react.createElement(Text, {
|
|
50
|
+
size: "sm",
|
|
51
|
+
className: "text-neutral-muted"
|
|
52
|
+
}, "Nothing runs until you confirm."))));
|
|
53
|
+
};
|
|
54
|
+
export { ApprovalPlan };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=ApprovalPlan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette/components/ApprovalPlan.js","sources":["../../../src/CommandPalette/components/ApprovalPlan.tsx"],"sourcesContent":["import React from \"react\";\nimport { Button } from \"@webiny/admin-ui\";\nimport { cn } from \"@webiny/admin-ui\";\nimport { Icon } from \"@webiny/admin-ui\";\nimport { Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as BoltIcon } from \"@webiny/icons/bolt.svg\";\nimport { ReactComponent as WarningIcon } from \"@webiny/icons/warning.svg\";\nimport type { AdminAssistantPendingApproval } from \"@webiny/app-admin\";\n\nexport interface ApprovalPlanProps {\n approvals: AdminAssistantPendingApproval[];\n busy: boolean;\n onApprove: () => void;\n onReject: () => void;\n}\n\n/**\n * The confirm gate for a proposed change.\n *\n * Arguments are shown as raw JSON on purpose. A prose summary would be the assistant describing its\n * own request — and the assistant is exactly what is not yet trusted here. What the user approves has\n * to be what actually runs.\n */\nexport const ApprovalPlan = ({ approvals, busy, onApprove, onReject }: ApprovalPlanProps) => {\n if (approvals.length === 0) {\n return null;\n }\n\n const destructive = approvals.some(approval => approval.destructive);\n\n let heading = `Approve ${approvals.length} changes`;\n if (approvals.length === 1) {\n heading = `Approve: ${approvals[0].title ?? approvals[0].toolName}`;\n }\n\n return (\n <div\n className={cn(\n \"mt-sm overflow-hidden rounded-md border border-neutral-dimmed\",\n destructive ? \"bg-destructive-subtle\" : \"bg-warning-subtle\"\n )}\n >\n <div className=\"flex items-center gap-sm border-b border-neutral-dimmed px-sm py-xs-plus\">\n <Icon\n icon={destructive ? <WarningIcon /> : <BoltIcon />}\n size=\"sm\"\n label=\"\"\n color=\"inherit\"\n className={destructive ? \"text-destructive-primary\" : undefined}\n />\n <Text size=\"sm\" className=\"font-semibold text-neutral-primary\">\n {heading}\n </Text>\n {destructive ? (\n <Text size=\"sm\" className=\"ml-auto text-destructive-primary\">\n Cannot be undone\n </Text>\n ) : null}\n </div>\n\n <div className=\"bg-neutral-base px-sm py-xs-plus\">\n {approvals.map(approval => (\n <div key={approval.approvalId} className=\"mb-xs\">\n <Text as=\"div\" size=\"sm\" className=\"font-mono text-neutral-strong\">\n {approval.toolName}\n </Text>\n <pre className=\"mt-xxs overflow-x-auto rounded bg-neutral-subtle p-sm text-xs text-neutral-strong\">\n {JSON.stringify(approval.input, null, 2)}\n </pre>\n </div>\n ))}\n\n <div className=\"mt-sm flex items-center gap-sm\">\n <Button variant=\"primary\" text=\"Run\" disabled={busy} onClick={onApprove} />\n <Button variant=\"secondary\" text=\"Reject\" disabled={busy} onClick={onReject} />\n <Text size=\"sm\" className=\"text-neutral-muted\">\n Nothing runs until you confirm.\n </Text>\n </div>\n </div>\n </div>\n );\n};\n"],"names":["ApprovalPlan","approvals","busy","onApprove","onReject","destructive","approval","heading","cn","Icon","WarningIcon","BoltIcon","undefined","Text","JSON","Button"],"mappings":";;;;AAuBO,MAAMA,eAAe,CAAC,EAAEC,SAAS,EAAEC,IAAI,EAAEC,SAAS,EAAEC,QAAQ,EAAqB;IACpF,IAAIH,AAAqB,MAArBA,UAAU,MAAM,EAChB,OAAO;IAGX,MAAMI,cAAcJ,UAAU,IAAI,CAACK,CAAAA,WAAYA,SAAS,WAAW;IAEnE,IAAIC,UAAU,CAAC,QAAQ,EAAEN,UAAU,MAAM,CAAC,QAAQ,CAAC;IACnD,IAAIA,AAAqB,MAArBA,UAAU,MAAM,EAChBM,UAAU,CAAC,SAAS,EAAEN,SAAS,CAAC,EAAE,CAAC,KAAK,IAAIA,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE;IAGvE,OAAO,WAAP,GACI,oBAAC;QACG,WAAWO,GACP,iEACAH,cAAc,0BAA0B;qBAG5C,oBAAC;QAAI,WAAU;qBACX,oBAACI,MAAIA;QACD,MAAMJ,cAAc,WAAdA,GAAc,oBAACK,4BAAWA,QAAAA,WAAAA,GAAM,oBAACC,gBAAQA;QAC/C,MAAK;QACL,OAAM;QACN,OAAM;QACN,WAAWN,cAAc,6BAA6BO;sBAE1D,oBAACC,MAAIA;QAAC,MAAK;QAAK,WAAU;OACrBN,UAEJF,cAAc,WAAdA,GACG,oBAACQ,MAAIA;QAAC,MAAK;QAAK,WAAU;OAAmC,sBAG7D,qBAGR,oBAAC;QAAI,WAAU;OACVZ,UAAU,GAAG,CAACK,CAAAA,WAAAA,WAAAA,GACX,oBAAC;YAAI,KAAKA,SAAS,UAAU;YAAE,WAAU;yBACrC,oBAACO,MAAIA;YAAC,IAAG;YAAM,MAAK;YAAK,WAAU;WAC9BP,SAAS,QAAQ,iBAEtB,oBAAC;YAAI,WAAU;WACVQ,KAAK,SAAS,CAACR,SAAS,KAAK,EAAE,MAAM,qBAKlD,oBAAC;QAAI,WAAU;qBACX,oBAACS,QAAMA;QAAC,SAAQ;QAAU,MAAK;QAAM,UAAUb;QAAM,SAASC;sBAC9D,oBAACY,QAAMA;QAAC,SAAQ;QAAY,MAAK;QAAS,UAAUb;QAAM,SAASE;sBACnE,oBAACS,MAAIA;QAAC,MAAK;QAAK,WAAU;OAAqB;AAOnE"}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import react from "react";
|
|
2
2
|
import { Command, useCommandState } from "cmdk";
|
|
3
|
-
import { Icon, Text } from "@webiny/admin-ui";
|
|
3
|
+
import { Icon, Text, cn } from "@webiny/admin-ui";
|
|
4
4
|
import { ReactComponent } from "@webiny/icons/keyboard_return.svg";
|
|
5
5
|
import { Kbd } from "./Kbd.js";
|
|
6
6
|
const CommandItemRow = ({ row })=>{
|
|
7
7
|
const selected = useCommandState((state)=>(state.value || "") === row.value);
|
|
8
|
+
let tile = "border-neutral-dimmed bg-neutral-subtle";
|
|
9
|
+
if (selected) tile = "border-primary bg-primary-subtle";
|
|
8
10
|
return /*#__PURE__*/ react.createElement(Command.Item, {
|
|
9
11
|
value: row.value,
|
|
10
12
|
onSelect: row.onRun,
|
|
11
13
|
className: "flex cursor-pointer items-center gap-sm rounded-md px-sm py-xs-plus data-[selected=true]:bg-neutral-dimmed"
|
|
12
14
|
}, /*#__PURE__*/ react.createElement("div", {
|
|
13
|
-
className: "grid size-xl shrink-0 place-items-center rounded-md border
|
|
15
|
+
className: cn("grid size-xl shrink-0 place-items-center rounded-md border", tile)
|
|
14
16
|
}, row.icon ?? null), /*#__PURE__*/ react.createElement("div", {
|
|
15
17
|
className: "min-w-0 flex-1"
|
|
16
18
|
}, /*#__PURE__*/ react.createElement(Text, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandPalette/components/CommandItemRow.js","sources":["../../../src/CommandPalette/components/CommandItemRow.tsx"],"sourcesContent":["import React from \"react\";\nimport { Command, useCommandState } from \"cmdk\";\nimport { Icon
|
|
1
|
+
{"version":3,"file":"CommandPalette/components/CommandItemRow.js","sources":["../../../src/CommandPalette/components/CommandItemRow.tsx"],"sourcesContent":["import React from \"react\";\nimport { Command, useCommandState } from \"cmdk\";\nimport { cn } from \"@webiny/admin-ui\";\nimport { Icon } from \"@webiny/admin-ui\";\nimport { Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as ReturnIcon } from \"@webiny/icons/keyboard_return.svg\";\nimport type { CommandRow } from \"../types.js\";\nimport { Kbd } from \"./Kbd.js\";\n\nexport const CommandItemRow = ({ row }: { row: CommandRow }) => {\n const selected = useCommandState(state => (state.value || \"\") === row.value);\n\n let tile = \"border-neutral-dimmed bg-neutral-subtle\";\n if (selected) {\n tile = \"border-primary bg-primary-subtle\";\n }\n\n return (\n <Command.Item\n value={row.value}\n onSelect={row.onRun}\n className=\"flex cursor-pointer items-center gap-sm rounded-md px-sm py-xs-plus data-[selected=true]:bg-neutral-dimmed\"\n >\n <div className={cn(\"grid size-xl shrink-0 place-items-center rounded-md border\", tile)}>\n {row.icon ?? null}\n </div>\n <div className=\"min-w-0 flex-1\">\n <Text as=\"div\" size=\"md\" className=\"truncate font-medium text-neutral-primary\">\n {row.label}\n </Text>\n {row.sub ? (\n <Text as=\"div\" size=\"sm\" className=\"truncate text-neutral-muted\">\n {row.sub}\n </Text>\n ) : null}\n </div>\n <div className=\"ml-auto flex shrink-0 items-center gap-xs\">\n {row.shortcut?.map((key, index) => (\n <Kbd key={index}>{key}</Kbd>\n ))}\n {selected ? (\n <span className=\"inline-flex items-center gap-xs rounded-sm bg-primary px-xs py-xs text-sm font-medium text-neutral-base\">\n {row.verb}\n <Icon icon={<ReturnIcon />} color={\"neutral-base\"} size={\"xs\"} label={\"\"} />\n </span>\n ) : null}\n </div>\n </Command.Item>\n );\n};\n"],"names":["CommandItemRow","row","selected","useCommandState","state","tile","Command","cn","Text","key","index","Kbd","Icon","ReturnIcon"],"mappings":";;;;;AASO,MAAMA,iBAAiB,CAAC,EAAEC,GAAG,EAAuB;IACvD,MAAMC,WAAWC,gBAAgBC,CAAAA,QAAUA,AAAAA,CAAAA,MAAM,KAAK,IAAI,EAAC,MAAOH,IAAI,KAAK;IAE3E,IAAII,OAAO;IACX,IAAIH,UACAG,OAAO;IAGX,OAAO,WAAP,GACI,oBAACC,QAAQ,IAAI;QACT,OAAOL,IAAI,KAAK;QAChB,UAAUA,IAAI,KAAK;QACnB,WAAU;qBAEV,oBAAC;QAAI,WAAWM,GAAG,8DAA8DF;OAC5EJ,IAAI,IAAI,IAAI,qBAEjB,oBAAC;QAAI,WAAU;qBACX,oBAACO,MAAIA;QAAC,IAAG;QAAM,MAAK;QAAK,WAAU;OAC9BP,IAAI,KAAK,GAEbA,IAAI,GAAG,GAAG,WAAH,GACJ,oBAACO,MAAIA;QAAC,IAAG;QAAM,MAAK;QAAK,WAAU;OAC9BP,IAAI,GAAG,IAEZ,qBAER,oBAAC;QAAI,WAAU;OACVA,IAAI,QAAQ,EAAE,IAAI,CAACQ,KAAKC,QAAAA,WAAAA,GACrB,oBAACC,KAAGA;YAAC,KAAKD;WAAQD,OAErBP,WAAW,WAAXA,GACG,oBAAC;QAAK,WAAU;OACXD,IAAI,IAAI,gBACT,oBAACW,MAAIA;QAAC,oBAAM,oBAACC,gBAAUA;QAAK,OAAO;QAAgB,MAAM;QAAM,OAAO;UAE1E;AAIpB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A dead end is the best moment to offer the assistant: the user has already expressed intent in
|
|
4
|
+
* words, so hand that exact query straight to AI rather than making them retype it.
|
|
5
|
+
*
|
|
6
|
+
* `onAskAi` is optional because the assistant is licensed separately. Without it this is a plain
|
|
7
|
+
* "nothing matched" state rather than an offer the project cannot accept.
|
|
8
|
+
*/
|
|
9
|
+
export interface NoResultsProps {
|
|
10
|
+
query: string;
|
|
11
|
+
onAskAi?: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const NoResults: ({ query, onAskAi }: NoResultsProps) => React.JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Button, Icon, Text } from "@webiny/admin-ui";
|
|
3
|
+
import { ReactComponent } from "@webiny/icons/search_off.svg";
|
|
4
|
+
import { ReactComponent as auto_awesome_svg_ReactComponent } from "@webiny/icons/auto_awesome.svg";
|
|
5
|
+
const NoResults = ({ query, onAskAi })=>/*#__PURE__*/ react.createElement("div", {
|
|
6
|
+
className: "flex flex-col items-center justify-center px-lg py-xxl text-center"
|
|
7
|
+
}, /*#__PURE__*/ react.createElement(Icon, {
|
|
8
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
9
|
+
size: "lg",
|
|
10
|
+
label: "",
|
|
11
|
+
color: "neutral-strong-transparent"
|
|
12
|
+
}), /*#__PURE__*/ react.createElement(Text, {
|
|
13
|
+
as: "div",
|
|
14
|
+
size: "lg",
|
|
15
|
+
className: "mt-sm font-semibold text-neutral-strong"
|
|
16
|
+
}, `No results for “${query}”`), /*#__PURE__*/ react.createElement(Text, {
|
|
17
|
+
as: "div",
|
|
18
|
+
size: "sm",
|
|
19
|
+
className: "mb-md mt-xxs text-neutral-muted"
|
|
20
|
+
}, onAskAi ? "No page or action matches. Ask the assistant instead." : "No page or action matches."), onAskAi ? /*#__PURE__*/ react.createElement(Button, {
|
|
21
|
+
variant: "secondary",
|
|
22
|
+
text: "Ask AI",
|
|
23
|
+
icon: /*#__PURE__*/ react.createElement(Icon, {
|
|
24
|
+
icon: /*#__PURE__*/ react.createElement(auto_awesome_svg_ReactComponent, null),
|
|
25
|
+
size: "sm",
|
|
26
|
+
label: "",
|
|
27
|
+
color: "inherit"
|
|
28
|
+
}),
|
|
29
|
+
onClick: onAskAi
|
|
30
|
+
}) : null);
|
|
31
|
+
export { NoResults };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=NoResults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette/components/NoResults.js","sources":["../../../src/CommandPalette/components/NoResults.tsx"],"sourcesContent":["import React from \"react\";\nimport { Button, Icon, Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as SearchOffIcon } from \"@webiny/icons/search_off.svg\";\nimport { ReactComponent as AiIcon } from \"@webiny/icons/auto_awesome.svg\";\n\n/**\n * A dead end is the best moment to offer the assistant: the user has already expressed intent in\n * words, so hand that exact query straight to AI rather than making them retype it.\n *\n * `onAskAi` is optional because the assistant is licensed separately. Without it this is a plain\n * \"nothing matched\" state rather than an offer the project cannot accept.\n */\nexport interface NoResultsProps {\n query: string;\n onAskAi?: () => void;\n}\n\nexport const NoResults = ({ query, onAskAi }: NoResultsProps) => (\n <div className=\"flex flex-col items-center justify-center px-lg py-xxl text-center\">\n <Icon icon={<SearchOffIcon />} size=\"lg\" label=\"\" color=\"neutral-strong-transparent\" />\n <Text as=\"div\" size=\"lg\" className=\"mt-sm font-semibold text-neutral-strong\">\n {`No results for “${query}”`}\n </Text>\n <Text as=\"div\" size=\"sm\" className=\"mb-md mt-xxs text-neutral-muted\">\n {onAskAi\n ? \"No page or action matches. Ask the assistant instead.\"\n : \"No page or action matches.\"}\n </Text>\n {onAskAi ? (\n <Button\n variant=\"secondary\"\n text=\"Ask AI\"\n icon={<Icon icon={<AiIcon />} size=\"sm\" label=\"\" color=\"inherit\" />}\n onClick={onAskAi}\n />\n ) : null}\n </div>\n);\n"],"names":["NoResults","query","onAskAi","Icon","SearchOffIcon","Text","Button","AiIcon"],"mappings":";;;;AAiBO,MAAMA,YAAY,CAAC,EAAEC,KAAK,EAAEC,OAAO,EAAkB,iBACxD,oBAAC;QAAI,WAAU;qBACX,oBAACC,MAAIA;QAAC,oBAAM,oBAACC,gBAAaA;QAAK,MAAK;QAAK,OAAM;QAAG,OAAM;sBACxD,oBAACC,MAAIA;QAAC,IAAG;QAAM,MAAK;QAAK,WAAU;OAC9B,CAAC,gBAAgB,EAAEJ,MAAM,CAAC,CAAC,iBAEhC,oBAACI,MAAIA;QAAC,IAAG;QAAM,MAAK;QAAK,WAAU;OAC9BH,UACK,0DACA,+BAETA,UAAU,WAAVA,GACG,oBAACI,QAAMA;QACH,SAAQ;QACR,MAAK;QACL,oBAAM,oBAACH,MAAIA;YAAC,oBAAM,oBAACI,iCAAMA;YAAK,MAAK;YAAK,OAAM;YAAG,OAAM;;QACvD,SAASL;SAEb"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface Hint {
|
|
3
|
+
keys: React.ReactNode;
|
|
4
|
+
label: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Hints are mode-specific: the shortcuts that matter while searching are not the ones that matter
|
|
8
|
+
* mid-conversation, and a static row would advertise keys that do nothing.
|
|
9
|
+
*/
|
|
10
|
+
export declare const PaletteFooter: ({ label, hints }: {
|
|
11
|
+
label: string;
|
|
12
|
+
hints: Hint[];
|
|
13
|
+
}) => React.JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Text } from "@webiny/admin-ui";
|
|
3
|
+
import { Kbd } from "./Kbd.js";
|
|
4
|
+
const PaletteFooter = ({ label, hints })=>/*#__PURE__*/ react.createElement("div", {
|
|
5
|
+
className: "flex flex-none items-center justify-between gap-sm border-t border-neutral-subtle bg-neutral-subtle px-sm py-xs-plus"
|
|
6
|
+
}, /*#__PURE__*/ react.createElement(Text, {
|
|
7
|
+
size: "sm",
|
|
8
|
+
className: "truncate text-neutral-muted"
|
|
9
|
+
}, label), /*#__PURE__*/ react.createElement("div", {
|
|
10
|
+
className: "flex shrink-0 items-center gap-md"
|
|
11
|
+
}, hints.map((hint)=>/*#__PURE__*/ react.createElement(Text, {
|
|
12
|
+
key: hint.label,
|
|
13
|
+
size: "sm",
|
|
14
|
+
className: "inline-flex items-center gap-xs text-neutral-muted"
|
|
15
|
+
}, /*#__PURE__*/ react.createElement(Kbd, null, hint.keys), hint.label))));
|
|
16
|
+
export { PaletteFooter };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=PaletteFooter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette/components/PaletteFooter.js","sources":["../../../src/CommandPalette/components/PaletteFooter.tsx"],"sourcesContent":["import React from \"react\";\nimport { Text } from \"@webiny/admin-ui\";\nimport { Kbd } from \"./Kbd.js\";\n\nexport interface Hint {\n keys: React.ReactNode;\n label: string;\n}\n\n/**\n * Hints are mode-specific: the shortcuts that matter while searching are not the ones that matter\n * mid-conversation, and a static row would advertise keys that do nothing.\n */\nexport const PaletteFooter = ({ label, hints }: { label: string; hints: Hint[] }) => (\n <div className=\"flex flex-none items-center justify-between gap-sm border-t border-neutral-subtle bg-neutral-subtle px-sm py-xs-plus\">\n <Text size=\"sm\" className=\"truncate text-neutral-muted\">\n {label}\n </Text>\n <div className=\"flex shrink-0 items-center gap-md\">\n {hints.map(hint => (\n <Text\n key={hint.label}\n size=\"sm\"\n className=\"inline-flex items-center gap-xs text-neutral-muted\"\n >\n <Kbd>{hint.keys}</Kbd>\n {hint.label}\n </Text>\n ))}\n </div>\n </div>\n);\n"],"names":["PaletteFooter","label","hints","Text","hint","Kbd"],"mappings":";;;AAaO,MAAMA,gBAAgB,CAAC,EAAEC,KAAK,EAAEC,KAAK,EAAoC,iBAC5E,oBAAC;QAAI,WAAU;qBACX,oBAACC,MAAIA;QAAC,MAAK;QAAK,WAAU;OACrBF,QAAAA,WAAAA,GAEL,oBAAC;QAAI,WAAU;OACVC,MAAM,GAAG,CAACE,CAAAA,OAAAA,WAAAA,GACP,oBAACD,MAAIA;YACD,KAAKC,KAAK,KAAK;YACf,MAAK;YACL,WAAU;yBAEV,oBAACC,KAAGA,MAAED,KAAK,IAAI,GACdA,KAAK,KAAK"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface ToolChipProps {
|
|
3
|
+
name: string;
|
|
4
|
+
/** Done chips read as confirmed work, failed ones as a call the model has to recover from. */
|
|
5
|
+
state: "running" | "done" | "failed";
|
|
6
|
+
}
|
|
7
|
+
export declare const ToolChip: ({ name, state }: ToolChipProps) => React.JSX.Element;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Icon, Text, cn } from "@webiny/admin-ui";
|
|
3
|
+
import { ReactComponent } from "@webiny/icons/check.svg";
|
|
4
|
+
import { ReactComponent as autorenew_svg_ReactComponent } from "@webiny/icons/autorenew.svg";
|
|
5
|
+
import { ReactComponent as error_svg_ReactComponent } from "@webiny/icons/error.svg";
|
|
6
|
+
const toolIcon = (state)=>{
|
|
7
|
+
if ("done" === state) return /*#__PURE__*/ react.createElement(ReactComponent, null);
|
|
8
|
+
if ("failed" === state) return /*#__PURE__*/ react.createElement(error_svg_ReactComponent, null);
|
|
9
|
+
return /*#__PURE__*/ react.createElement(autorenew_svg_ReactComponent, null);
|
|
10
|
+
};
|
|
11
|
+
const ToolChip = ({ name, state })=>{
|
|
12
|
+
const done = "done" === state;
|
|
13
|
+
const failed = "failed" === state;
|
|
14
|
+
let tone = "border-neutral-dimmed bg-neutral-subtle text-neutral-strong";
|
|
15
|
+
if (done) tone = "border-success-subtle bg-success-subtle text-success";
|
|
16
|
+
else if (failed) tone = "border-destructive-subtle bg-destructive-subtle text-destructive-primary";
|
|
17
|
+
return /*#__PURE__*/ react.createElement("span", {
|
|
18
|
+
className: cn("inline-flex items-center gap-xs rounded-xl border px-sm py-xxs", tone)
|
|
19
|
+
}, /*#__PURE__*/ react.createElement(Icon, {
|
|
20
|
+
icon: toolIcon(state),
|
|
21
|
+
size: "xs",
|
|
22
|
+
label: "",
|
|
23
|
+
color: "inherit",
|
|
24
|
+
className: "running" === state ? "animate-spin" : void 0
|
|
25
|
+
}), /*#__PURE__*/ react.createElement(Text, {
|
|
26
|
+
size: "sm",
|
|
27
|
+
className: "font-mono"
|
|
28
|
+
}, name));
|
|
29
|
+
};
|
|
30
|
+
export { ToolChip };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=ToolChip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette/components/ToolChip.js","sources":["../../../src/CommandPalette/components/ToolChip.tsx"],"sourcesContent":["import React from \"react\";\nimport { cn } from \"@webiny/admin-ui\";\nimport { Icon } from \"@webiny/admin-ui\";\nimport { Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as CheckIcon } from \"@webiny/icons/check.svg\";\nimport { ReactComponent as SpinnerIcon } from \"@webiny/icons/autorenew.svg\";\nimport { ReactComponent as ErrorIcon } from \"@webiny/icons/error.svg\";\n\nexport interface ToolChipProps {\n name: string;\n /** Done chips read as confirmed work, failed ones as a call the model has to recover from. */\n state: \"running\" | \"done\" | \"failed\";\n}\n\n/**\n * One tool the assistant called. Icon colour comes from the parent because `Icon` only offers\n * neutral/accent variants — `inherit` lets the chip's own text colour drive it.\n */\n/*\n * Lower-case on purpose: this picks an element, it is not a component. `Icon` does\n * `cloneElement(icon, { className })` to apply size, colour and the spin animation, so the SVG\n * element itself has to be what reaches it. Wrapping this in a component would hand those classes to\n * the wrapper, which drops them, and the chips would silently lose their styling.\n */\nconst toolIcon = (state: ToolChipProps[\"state\"]) => {\n if (state === \"done\") {\n return <CheckIcon />;\n }\n\n if (state === \"failed\") {\n return <ErrorIcon />;\n }\n\n return <SpinnerIcon />;\n};\n\nexport const ToolChip = ({ name, state }: ToolChipProps) => {\n const done = state === \"done\";\n const failed = state === \"failed\";\n\n let tone = \"border-neutral-dimmed bg-neutral-subtle text-neutral-strong\";\n if (done) {\n tone = \"border-success-subtle bg-success-subtle text-success\";\n } else if (failed) {\n tone = \"border-destructive-subtle bg-destructive-subtle text-destructive-primary\";\n }\n\n return (\n <span\n className={cn(\"inline-flex items-center gap-xs rounded-xl border px-sm py-xxs\", tone)}\n >\n <Icon\n icon={toolIcon(state)}\n size=\"xs\"\n label=\"\"\n color=\"inherit\"\n className={state === \"running\" ? \"animate-spin\" : undefined}\n />\n <Text size=\"sm\" className=\"font-mono\">\n {name}\n </Text>\n </span>\n );\n};\n"],"names":["toolIcon","state","CheckIcon","ErrorIcon","SpinnerIcon","ToolChip","name","done","failed","tone","cn","Icon","undefined","Text"],"mappings":";;;;;AAwBA,MAAMA,WAAW,CAACC;IACd,IAAIA,AAAU,WAAVA,OACA,OAAO,WAAP,GAAO,oBAACC,gBAASA;IAGrB,IAAID,AAAU,aAAVA,OACA,OAAO,WAAP,GAAO,oBAACE,0BAASA;IAGrB,OAAO,WAAP,GAAO,oBAACC,8BAAWA;AACvB;AAEO,MAAMC,WAAW,CAAC,EAAEC,IAAI,EAAEL,KAAK,EAAiB;IACnD,MAAMM,OAAON,AAAU,WAAVA;IACb,MAAMO,SAASP,AAAU,aAAVA;IAEf,IAAIQ,OAAO;IACX,IAAIF,MACAE,OAAO;SACJ,IAAID,QACPC,OAAO;IAGX,OAAO,WAAP,GACI,oBAAC;QACG,WAAWC,GAAG,kEAAkED;qBAEhF,oBAACE,MAAIA;QACD,MAAMX,SAASC;QACf,MAAK;QACL,OAAM;QACN,OAAM;QACN,WAAWA,AAAU,cAAVA,QAAsB,iBAAiBW;sBAEtD,oBAACC,MAAIA;QAAC,MAAK;QAAK,WAAU;OACrBP;AAIjB"}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
1
|
+
export { CommandDetail } from "./CommandDetail.js";
|
|
2
|
+
export { CommandItemRow } from "./CommandItemRow.js";
|
|
3
|
+
export { GroupHeading } from "./GroupHeading.js";
|
|
4
|
+
export { HintIcon } from "./HintIcon.js";
|
|
5
|
+
export { Kbd } from "./Kbd.js";
|
|
6
|
+
export { AiModeBadge } from "./AiModeBadge.js";
|
|
7
|
+
export { AiSuggestions, AI_SUGGESTIONS } from "./AiSuggestions.js";
|
|
8
|
+
export { AiTurn } from "./AiTurn.js";
|
|
9
|
+
export { ApprovalPlan } from "./ApprovalPlan.js";
|
|
10
|
+
export { AnswerSkeleton } from "./AnswerSkeleton.js";
|
|
11
|
+
export { NoResults } from "./NoResults.js";
|
|
12
|
+
export { PaletteFooter, type Hint } from "./PaletteFooter.js";
|
|
13
|
+
export { ToolChip } from "./ToolChip.js";
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
1
|
+
export { CommandDetail } from "./CommandDetail.js";
|
|
2
|
+
export { CommandItemRow } from "./CommandItemRow.js";
|
|
3
|
+
export { GroupHeading } from "./GroupHeading.js";
|
|
4
|
+
export { HintIcon } from "./HintIcon.js";
|
|
5
|
+
export { Kbd } from "./Kbd.js";
|
|
6
|
+
export { AiModeBadge } from "./AiModeBadge.js";
|
|
7
|
+
export { AI_SUGGESTIONS, AiSuggestions } from "./AiSuggestions.js";
|
|
8
|
+
export { AiTurn } from "./AiTurn.js";
|
|
9
|
+
export { ApprovalPlan } from "./ApprovalPlan.js";
|
|
10
|
+
export { AnswerSkeleton } from "./AnswerSkeleton.js";
|
|
11
|
+
export { NoResults } from "./NoResults.js";
|
|
12
|
+
export { PaletteFooter } from "./PaletteFooter.js";
|
|
13
|
+
export { ToolChip } from "./ToolChip.js";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import type { Hint } from "../components/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* What a mode needs from the palette while it is handling a key.
|
|
5
|
+
*
|
|
6
|
+
* The palette owns the query and the input element, because there is ONE input row across every
|
|
7
|
+
* mode and switching must not move or remount it. A mode reads and writes the query through this
|
|
8
|
+
* rather than holding its own.
|
|
9
|
+
*/
|
|
10
|
+
export interface PaletteModeKeyContext {
|
|
11
|
+
query: string;
|
|
12
|
+
setQuery(value: string): void;
|
|
13
|
+
/** Leave this mode and return to the command list. */
|
|
14
|
+
exit(): void;
|
|
15
|
+
}
|
|
16
|
+
/** How the palette should present itself while this mode is active. */
|
|
17
|
+
export interface PaletteModeAppearance {
|
|
18
|
+
/** Rendered in the input row, ahead of the input itself. */
|
|
19
|
+
icon: React.ReactNode;
|
|
20
|
+
iconColor: "accent" | "neutral-light";
|
|
21
|
+
iconLabel: string;
|
|
22
|
+
/** Optional marker beside the icon, e.g. a mode name pill. */
|
|
23
|
+
badge?: React.ReactNode;
|
|
24
|
+
placeholder: string;
|
|
25
|
+
footerLabel: string;
|
|
26
|
+
hints: Hint[];
|
|
27
|
+
/**
|
|
28
|
+
* Taller panel. A conversation grows and wants the room; a command list does not, and a list
|
|
29
|
+
* stretched to full height looks broken when it holds three items.
|
|
30
|
+
*/
|
|
31
|
+
tall: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One way the palette can behave.
|
|
35
|
+
*
|
|
36
|
+
* A mode supplies its body, its keys and how the palette should look while it is active; the palette
|
|
37
|
+
* owns the shell, the query and the input. The point of the split is that adding a mode does not
|
|
38
|
+
* mean editing the palette: everything AI lives in `createAiMode`, and the palette only knows this
|
|
39
|
+
* interface.
|
|
40
|
+
*
|
|
41
|
+
* `appearance` and `body` are read during render, so an implementation can serve them from getters
|
|
42
|
+
* over observable state and let a reactive palette re-render on its own.
|
|
43
|
+
*/
|
|
44
|
+
export interface PaletteMode {
|
|
45
|
+
appearance: PaletteModeAppearance;
|
|
46
|
+
/** Rendered in the palette's scroll area, in place of the command list. */
|
|
47
|
+
body: React.ReactNode;
|
|
48
|
+
/**
|
|
49
|
+
* Enter the mode, optionally carrying what the user had already typed.
|
|
50
|
+
*
|
|
51
|
+
* The seed exists for ONE entry point: the "Ask AI" button in the no-results state. A command
|
|
52
|
+
* search that found nothing already holds a sentence the user typed, and the button turns it
|
|
53
|
+
* into the question instead of making them retype it. Every other way in (space on an empty
|
|
54
|
+
* query, `mod+k`, selecting the Ask AI command) passes nothing and leaves an empty input.
|
|
55
|
+
*
|
|
56
|
+
* The palette calls this; the mode decides what a seed means. Returning focus to the shared
|
|
57
|
+
* input is the palette's job, since the input is the palette's.
|
|
58
|
+
*/
|
|
59
|
+
enter(seed?: string): void;
|
|
60
|
+
/** Drop any state. Called when the mode is left and when the palette closes. */
|
|
61
|
+
reset(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Handle a key while this mode is active. Return true when the key was consumed, so the palette
|
|
64
|
+
* leaves it alone.
|
|
65
|
+
*/
|
|
66
|
+
handleKey(event: React.KeyboardEvent, context: PaletteModeKeyContext): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Called after the palette renders this mode's body, with the scroll container it was rendered
|
|
69
|
+
* into. For a mode whose body grows, such as a conversation, this is where it keeps the newest
|
|
70
|
+
* content in view. The element belongs to the palette; a mode only reads or scrolls it.
|
|
71
|
+
*/
|
|
72
|
+
afterRender?(scrollContainer: HTMLElement): void;
|
|
73
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AdminAssistantPresenter } from "@webiny/app-admin";
|
|
2
|
+
import type { PaletteMode } from "./PaletteMode.js";
|
|
3
|
+
/**
|
|
4
|
+
* The assistant, as a palette mode.
|
|
5
|
+
*
|
|
6
|
+
* Everything specific to it lives here: what the input row shows, what Enter and Backspace do, and
|
|
7
|
+
* what fills the panel. The conversation itself belongs to `AdminAssistantPresenter`.
|
|
8
|
+
*
|
|
9
|
+
* A plain object rather than a hook. `appearance` and `body` are getters, so reading them during a
|
|
10
|
+
* reactive component's render tracks the presenter's observables and re-renders on a new turn, with
|
|
11
|
+
* no dependency arrays to keep honest.
|
|
12
|
+
*/
|
|
13
|
+
export declare const createAiMode: (presenter: AdminAssistantPresenter.Interface) => PaletteMode;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { ReactComponent } from "@webiny/icons/auto_awesome.svg";
|
|
3
|
+
import { ReactComponent as keyboard_return_svg_ReactComponent } from "@webiny/icons/keyboard_return.svg";
|
|
4
|
+
import { ReactComponent as backspace_svg_ReactComponent } from "@webiny/icons/backspace.svg";
|
|
5
|
+
import { AiModeBadge, AiSuggestions, AiTurn, HintIcon } from "../components/index.js";
|
|
6
|
+
const HINTS = [
|
|
7
|
+
{
|
|
8
|
+
keys: /*#__PURE__*/ react.createElement(HintIcon, {
|
|
9
|
+
element: /*#__PURE__*/ react.createElement(keyboard_return_svg_ReactComponent, null)
|
|
10
|
+
}),
|
|
11
|
+
label: "Ask"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
keys: /*#__PURE__*/ react.createElement(HintIcon, {
|
|
15
|
+
element: /*#__PURE__*/ react.createElement(backspace_svg_ReactComponent, null)
|
|
16
|
+
}),
|
|
17
|
+
label: "Commands"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
keys: "esc",
|
|
21
|
+
label: "Close"
|
|
22
|
+
}
|
|
23
|
+
];
|
|
24
|
+
const createAiMode = (presenter)=>({
|
|
25
|
+
get appearance () {
|
|
26
|
+
const started = presenter.vm.turns.length > 0;
|
|
27
|
+
return {
|
|
28
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
29
|
+
iconColor: "accent",
|
|
30
|
+
iconLabel: "Ask AI",
|
|
31
|
+
badge: /*#__PURE__*/ react.createElement(AiModeBadge, null),
|
|
32
|
+
placeholder: started ? "Ask a follow-up…" : "Ask about this project…",
|
|
33
|
+
footerLabel: "Webiny AI",
|
|
34
|
+
hints: HINTS,
|
|
35
|
+
tall: true
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
get body () {
|
|
39
|
+
const { turns, busy } = presenter.vm;
|
|
40
|
+
if (0 === turns.length) return /*#__PURE__*/ react.createElement(AiSuggestions, {
|
|
41
|
+
onAsk: (question)=>presenter.ask(question)
|
|
42
|
+
});
|
|
43
|
+
return turns.map((turn, index)=>/*#__PURE__*/ react.createElement(AiTurn, {
|
|
44
|
+
key: index,
|
|
45
|
+
turn: turn,
|
|
46
|
+
initials: "You",
|
|
47
|
+
busy: busy,
|
|
48
|
+
onApprove: ()=>presenter.decide(index, true),
|
|
49
|
+
onReject: ()=>presenter.decide(index, false)
|
|
50
|
+
}));
|
|
51
|
+
},
|
|
52
|
+
enter (seed) {
|
|
53
|
+
if (seed?.trim()) presenter.ask(seed);
|
|
54
|
+
},
|
|
55
|
+
reset () {
|
|
56
|
+
presenter.reset();
|
|
57
|
+
},
|
|
58
|
+
handleKey (event, context) {
|
|
59
|
+
if ("Enter" === event.key) {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
presenter.ask(context.query);
|
|
62
|
+
context.setQuery("");
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if ("Backspace" === event.key && "" === context.query) {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
context.exit();
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
},
|
|
72
|
+
afterRender (container) {
|
|
73
|
+
container.scrollTo({
|
|
74
|
+
top: container.scrollHeight
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
export { createAiMode };
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=createAiMode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette/modes/createAiMode.js","sources":["../../../src/CommandPalette/modes/createAiMode.tsx"],"sourcesContent":["import React from \"react\";\nimport type { AdminAssistantPresenter } from \"@webiny/app-admin\";\nimport { ReactComponent as AiIcon } from \"@webiny/icons/auto_awesome.svg\";\nimport { ReactComponent as ReturnIcon } from \"@webiny/icons/keyboard_return.svg\";\nimport { ReactComponent as BackspaceIcon } from \"@webiny/icons/backspace.svg\";\nimport { AiModeBadge, AiSuggestions, AiTurn, HintIcon, type Hint } from \"../components/index.js\";\nimport type { PaletteMode, PaletteModeKeyContext } from \"./PaletteMode.js\";\n\nconst HINTS: Hint[] = [\n { keys: <HintIcon element={<ReturnIcon />} />, label: \"Ask\" },\n { keys: <HintIcon element={<BackspaceIcon />} />, label: \"Commands\" },\n { keys: \"esc\", label: \"Close\" }\n];\n\n/**\n * The assistant, as a palette mode.\n *\n * Everything specific to it lives here: what the input row shows, what Enter and Backspace do, and\n * what fills the panel. The conversation itself belongs to `AdminAssistantPresenter`.\n *\n * A plain object rather than a hook. `appearance` and `body` are getters, so reading them during a\n * reactive component's render tracks the presenter's observables and re-renders on a new turn, with\n * no dependency arrays to keep honest.\n */\nexport const createAiMode = (presenter: AdminAssistantPresenter.Interface): PaletteMode => ({\n get appearance() {\n const started = presenter.vm.turns.length > 0;\n\n return {\n icon: <AiIcon />,\n iconColor: \"accent\" as const,\n iconLabel: \"Ask AI\",\n badge: <AiModeBadge />,\n placeholder: started ? \"Ask a follow-up…\" : \"Ask about this project…\",\n footerLabel: \"Webiny AI\",\n hints: HINTS,\n tall: true\n };\n },\n\n get body() {\n const { turns, busy } = presenter.vm;\n\n if (turns.length === 0) {\n return <AiSuggestions onAsk={question => presenter.ask(question)} />;\n }\n\n return turns.map((turn, index) => (\n <AiTurn\n key={index}\n turn={turn}\n initials=\"You\"\n busy={busy}\n onApprove={() => presenter.decide(index, true)}\n onReject={() => presenter.decide(index, false)}\n />\n ));\n },\n\n // A seed only arrives from the no-results \"Ask AI\" button; see `PaletteMode.enter`.\n enter(seed?: string) {\n if (seed?.trim()) {\n presenter.ask(seed);\n }\n },\n\n reset() {\n presenter.reset();\n },\n\n handleKey(event: React.KeyboardEvent, context: PaletteModeKeyContext) {\n if (event.key === \"Enter\") {\n event.preventDefault();\n presenter.ask(context.query);\n context.setQuery(\"\");\n return true;\n }\n\n // Backspace on an empty input leaves the mode, mirroring how space entered it.\n if (event.key === \"Backspace\" && context.query === \"\") {\n event.preventDefault();\n context.exit();\n return true;\n }\n\n return false;\n },\n\n // Answers are long enough to push earlier turns off-screen, so keep the newest one visible.\n afterRender(container: HTMLElement) {\n container.scrollTo({ top: container.scrollHeight });\n }\n});\n"],"names":["HINTS","HintIcon","ReturnIcon","BackspaceIcon","createAiMode","presenter","started","AiIcon","AiModeBadge","turns","busy","AiSuggestions","question","turn","index","AiTurn","seed","event","context","container"],"mappings":";;;;;AAQA,MAAMA,QAAgB;IAClB;QAAE,MAAM,WAAN,GAAM,oBAACC,UAAQA;YAAC,uBAAS,oBAACC,oCAAUA;;QAAS,OAAO;IAAM;IAC5D;QAAE,MAAM,WAAN,GAAM,oBAACD,UAAQA;YAAC,uBAAS,oBAACE,8BAAaA;;QAAS,OAAO;IAAW;IACpE;QAAE,MAAM;QAAO,OAAO;IAAQ;CACjC;AAYM,MAAMC,eAAe,CAACC,YAA+D;QACxF,IAAI,cAAa;YACb,MAAMC,UAAUD,UAAU,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG;YAE5C,OAAO;gBACH,MAAM,WAAN,GAAM,oBAACE,gBAAMA;gBACb,WAAW;gBACX,WAAW;gBACX,OAAO,WAAP,GAAO,oBAACC,aAAWA;gBACnB,aAAaF,UAAU,qBAAqB;gBAC5C,aAAa;gBACb,OAAON;gBACP,MAAM;YACV;QACJ;QAEA,IAAI,QAAO;YACP,MAAM,EAAES,KAAK,EAAEC,IAAI,EAAE,GAAGL,UAAU,EAAE;YAEpC,IAAII,AAAiB,MAAjBA,MAAM,MAAM,EACZ,OAAO,WAAP,GAAO,oBAACE,eAAaA;gBAAC,OAAOC,CAAAA,WAAYP,UAAU,GAAG,CAACO;;YAG3D,OAAOH,MAAM,GAAG,CAAC,CAACI,MAAMC,QAAAA,WAAAA,GACpB,oBAACC,QAAMA;oBACH,KAAKD;oBACL,MAAMD;oBACN,UAAS;oBACT,MAAMH;oBACN,WAAW,IAAML,UAAU,MAAM,CAACS,OAAO;oBACzC,UAAU,IAAMT,UAAU,MAAM,CAACS,OAAO;;QAGpD;QAGA,OAAME,IAAa;YACf,IAAIA,MAAM,QACNX,UAAU,GAAG,CAACW;QAEtB;QAEA;YACIX,UAAU,KAAK;QACnB;QAEA,WAAUY,KAA0B,EAAEC,OAA8B;YAChE,IAAID,AAAc,YAAdA,MAAM,GAAG,EAAc;gBACvBA,MAAM,cAAc;gBACpBZ,UAAU,GAAG,CAACa,QAAQ,KAAK;gBAC3BA,QAAQ,QAAQ,CAAC;gBACjB,OAAO;YACX;YAGA,IAAID,AAAc,gBAAdA,MAAM,GAAG,IAAoBC,AAAkB,OAAlBA,QAAQ,KAAK,EAAS;gBACnDD,MAAM,cAAc;gBACpBC,QAAQ,IAAI;gBACZ,OAAO;YACX;YAEA,OAAO;QACX;QAGA,aAAYC,SAAsB;YAC9BA,UAAU,QAAQ,CAAC;gBAAE,KAAKA,UAAU,YAAY;YAAC;QACrD;IACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createAiMode } from "./createAiMode.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CommandPalettePresenter } from "@webiny/app-admin";
|
|
2
|
+
interface PaletteHotkeysParams {
|
|
3
|
+
presenter: CommandPalettePresenter.Interface;
|
|
4
|
+
close: () => void;
|
|
5
|
+
/** False when the license blocks the assistant, so mod+k must not cycle into it. */
|
|
6
|
+
aiEnabled: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The palette's global keys: the ones that work while it is closed, or while focus is not in the
|
|
10
|
+
* input. Keys that only mean something while typing stay on the input's `onKeyDown`.
|
|
11
|
+
*
|
|
12
|
+
* Reads the view model during render, so a reactive component calling this still re-renders when
|
|
13
|
+
* the palette opens, a detail view appears, or AI mode is entered.
|
|
14
|
+
*/
|
|
15
|
+
export declare const usePaletteHotkeys: ({ presenter, close, aiEnabled }: PaletteHotkeysParams) => void;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useHotkeys } from "@webiny/app-admin";
|
|
3
|
+
import { PALETTE_HOTKEY_ZINDEX } from "./constants.js";
|
|
4
|
+
const usePaletteHotkeys = ({ presenter, close, aiEnabled })=>{
|
|
5
|
+
const { isOpen, activeCommand, aiModeActive } = presenter.vm;
|
|
6
|
+
const keys = useMemo(()=>({
|
|
7
|
+
"mod+k": (e)=>{
|
|
8
|
+
e.preventDefault();
|
|
9
|
+
if (!isOpen) return void presenter.open();
|
|
10
|
+
if (activeCommand) return void presenter.cancelCommand();
|
|
11
|
+
if (aiEnabled && !aiModeActive) return void presenter.enterAiMode();
|
|
12
|
+
close();
|
|
13
|
+
},
|
|
14
|
+
backspace: (e)=>{
|
|
15
|
+
const target = e.target;
|
|
16
|
+
const editable = target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target?.isContentEditable;
|
|
17
|
+
if (!isOpen || !activeCommand || editable) return;
|
|
18
|
+
e.preventDefault();
|
|
19
|
+
presenter.cancelCommand();
|
|
20
|
+
},
|
|
21
|
+
...presenter.shortcutKeys
|
|
22
|
+
}), [
|
|
23
|
+
presenter,
|
|
24
|
+
presenter.shortcutKeys,
|
|
25
|
+
isOpen,
|
|
26
|
+
activeCommand,
|
|
27
|
+
aiModeActive,
|
|
28
|
+
close,
|
|
29
|
+
aiEnabled
|
|
30
|
+
]);
|
|
31
|
+
useHotkeys({
|
|
32
|
+
zIndex: PALETTE_HOTKEY_ZINDEX,
|
|
33
|
+
keys
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
export { usePaletteHotkeys };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=usePaletteHotkeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette/usePaletteHotkeys.js","sources":["../../src/CommandPalette/usePaletteHotkeys.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport { useHotkeys, type CommandPalettePresenter } from \"@webiny/app-admin\";\nimport { PALETTE_HOTKEY_ZINDEX } from \"./constants.js\";\n\ninterface PaletteHotkeysParams {\n presenter: CommandPalettePresenter.Interface;\n /* Not `presenter.close`: closing also resets the mode, which is the palette's business. */\n close: () => void;\n /** False when the license blocks the assistant, so mod+k must not cycle into it. */\n aiEnabled: boolean;\n}\n\n/**\n * The palette's global keys: the ones that work while it is closed, or while focus is not in the\n * input. Keys that only mean something while typing stay on the input's `onKeyDown`.\n *\n * Reads the view model during render, so a reactive component calling this still re-renders when\n * the palette opens, a detail view appears, or AI mode is entered.\n */\nexport const usePaletteHotkeys = ({ presenter, close, aiEnabled }: PaletteHotkeysParams) => {\n const { isOpen, activeCommand, aiModeActive } = presenter.vm;\n\n /*\n * mod+k cycles closed -> commands -> AI -> closed, so the same key that opens the palette also\n * reaches the assistant without the user having to know about the space shortcut. Closing from AI\n * mode keeps mod+k a way OUT of the palette, which is what it does everywhere else.\n * Backspace backs out of a detail view; command shortcuts run directly.\n */\n const keys = useMemo(\n () => ({\n \"mod+k\": (e: KeyboardEvent) => {\n e.preventDefault();\n\n if (!isOpen) {\n presenter.open();\n return;\n }\n\n /*\n * A detail view renders in place of the command list, so switching to AI mode from\n * there would put the user in a mode they cannot see. Back out to the list instead.\n */\n if (activeCommand) {\n presenter.cancelCommand();\n return;\n }\n\n if (aiEnabled && !aiModeActive) {\n presenter.enterAiMode();\n return;\n }\n\n close();\n },\n backspace: (e: KeyboardEvent) => {\n /*\n * This listener is global and stays registered while the palette is closed, so it\n * must leave Backspace alone unless there is a detail view to back out of, and never\n * touch it inside an input, textarea or rich text editor.\n */\n const target = e.target as HTMLElement | null;\n const editable =\n target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target?.isContentEditable;\n if (!isOpen || !activeCommand || editable) {\n return;\n }\n e.preventDefault();\n presenter.cancelCommand();\n },\n ...presenter.shortcutKeys\n }),\n [presenter, presenter.shortcutKeys, isOpen, activeCommand, aiModeActive, close, aiEnabled]\n );\n\n useHotkeys({ zIndex: PALETTE_HOTKEY_ZINDEX, keys });\n};\n"],"names":["usePaletteHotkeys","presenter","close","aiEnabled","isOpen","activeCommand","aiModeActive","keys","useMemo","e","target","editable","HTMLInputElement","HTMLTextAreaElement","useHotkeys","PALETTE_HOTKEY_ZINDEX"],"mappings":";;;AAmBO,MAAMA,oBAAoB,CAAC,EAAEC,SAAS,EAAEC,KAAK,EAAEC,SAAS,EAAwB;IACnF,MAAM,EAAEC,MAAM,EAAEC,aAAa,EAAEC,YAAY,EAAE,GAAGL,UAAU,EAAE;IAQ5D,MAAMM,OAAOC,QACT,IAAO;YACH,SAAS,CAACC;gBACNA,EAAE,cAAc;gBAEhB,IAAI,CAACL,QAAQ,YACTH,UAAU,IAAI;gBAQlB,IAAII,eAAe,YACfJ,UAAU,aAAa;gBAI3B,IAAIE,aAAa,CAACG,cAAc,YAC5BL,UAAU,WAAW;gBAIzBC;YACJ;YACA,WAAW,CAACO;gBAMR,MAAMC,SAASD,EAAE,MAAM;gBACvB,MAAME,WACFD,kBAAkBE,oBAClBF,kBAAkBG,uBAClBH,QAAQ;gBACZ,IAAI,CAACN,UAAU,CAACC,iBAAiBM,UAC7B;gBAEJF,EAAE,cAAc;gBAChBR,UAAU,aAAa;YAC3B;YACA,GAAGA,UAAU,YAAY;QAC7B,IACA;QAACA;QAAWA,UAAU,YAAY;QAAEG;QAAQC;QAAeC;QAAcJ;QAAOC;KAAU;IAG9FW,WAAW;QAAE,QAAQC;QAAuBR;IAAK;AACrD"}
|
package/Dashboard/Welcome.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
declare const
|
|
2
|
+
declare const WelcomeBase: () => React.JSX.Element;
|
|
3
|
+
declare const Welcome: typeof WelcomeBase & React.NamedExoticComponent<unknown> & {
|
|
4
|
+
readonly type: typeof WelcomeBase;
|
|
5
|
+
};
|
|
3
6
|
export default Welcome;
|