@webiny/app-admin-ui 0.0.0-unstable.e6f0dc8ca7 → 0.0.0-unstable.eb81deee7e
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 +6 -0
- package/CommandPalette/CommandPalette.js +202 -0
- package/CommandPalette/CommandPalette.js.map +1 -0
- 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/CommandDetail.d.ts +13 -0
- package/CommandPalette/components/CommandDetail.js +39 -0
- package/CommandPalette/components/CommandDetail.js.map +1 -0
- package/CommandPalette/components/CommandItemRow.d.ts +5 -0
- package/CommandPalette/components/CommandItemRow.js +41 -0
- package/CommandPalette/components/CommandItemRow.js.map +1 -0
- package/CommandPalette/components/GroupHeading.d.ts +4 -0
- package/CommandPalette/components/GroupHeading.js +10 -0
- package/CommandPalette/components/GroupHeading.js.map +1 -0
- package/CommandPalette/components/HintIcon.d.ts +4 -0
- package/CommandPalette/components/HintIcon.js +11 -0
- package/CommandPalette/components/HintIcon.js.map +1 -0
- package/CommandPalette/components/Kbd.d.ts +4 -0
- package/CommandPalette/components/Kbd.js +14 -0
- package/CommandPalette/components/Kbd.js.map +1 -0
- 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 -0
- package/CommandPalette/components/index.js +13 -0
- package/CommandPalette/constants.d.ts +8 -0
- package/CommandPalette/constants.js +5 -0
- package/CommandPalette/constants.js.map +1 -0
- package/CommandPalette/deriveRows.d.ts +19 -0
- package/CommandPalette/deriveRows.js +100 -0
- package/CommandPalette/deriveRows.js.map +1 -0
- 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/types.d.ts +15 -0
- package/CommandPalette/types.js +0 -0
- package/CommandPalette/usePaletteHotkeys.d.ts +16 -0
- package/CommandPalette/usePaletteHotkeys.js +38 -0
- package/CommandPalette/usePaletteHotkeys.js.map +1 -0
- package/Dashboard/Welcome.js +29 -33
- package/Dashboard/Welcome.js.map +1 -1
- package/Dashboard/components/AssistanceWidget.js +51 -52
- package/Dashboard/components/AssistanceWidget.js.map +1 -1
- package/Dashboard/components/CommunityWidget.js +55 -63
- package/Dashboard/components/CommunityWidget.js.map +1 -1
- package/Dashboard/components/MissingPermissionsWidget.js +13 -14
- package/Dashboard/components/MissingPermissionsWidget.js.map +1 -1
- package/Dashboard/components/assets/github.js +14 -0
- package/Dashboard/components/assets/github.js.map +1 -0
- package/Dashboard/components/assets/slack.js +27 -0
- package/Dashboard/components/assets/slack.js.map +1 -0
- package/Dashboard/components/assets/x-twitter.js +18 -0
- package/Dashboard/components/assets/x-twitter.js.map +1 -0
- package/Dashboard/components/assets/youtube.js +28 -0
- package/Dashboard/components/assets/youtube.js.map +1 -0
- package/Dashboard/components/index.js +0 -2
- package/Dashboard.js +6 -7
- package/Dashboard.js.map +1 -1
- package/Dialog/DialogContainer.js +54 -67
- package/Dialog/DialogContainer.js.map +1 -1
- package/Dialog/DialogProvider.js +5 -8
- package/Dialog/DialogProvider.js.map +1 -1
- package/Dialog.js +5 -9
- package/Dialog.js.map +1 -1
- package/Layout.js +50 -29
- package/Layout.js.map +1 -1
- package/Logo.js +12 -16
- package/Logo.js.map +1 -1
- package/Navigation/Navigation.js +30 -34
- package/Navigation/Navigation.js.map +1 -1
- package/Navigation/SidebarMenuItems.js +32 -44
- package/Navigation/SidebarMenuItems.js.map +1 -1
- package/NotFound/notFound.js +297 -0
- package/NotFound/notFound.js.map +1 -0
- package/NotFound.js +17 -18
- package/NotFound.js.map +1 -1
- package/UserMenu/UserMenu.js +17 -25
- package/UserMenu/UserMenu.js.map +1 -1
- package/UserMenu/UserMenuHandle.js +33 -46
- package/UserMenu/UserMenuHandle.js.map +1 -1
- package/UserMenu/UserMenuItem.js +9 -12
- package/UserMenu/UserMenuItem.js.map +1 -1
- package/UserMenu/UserMenuLink.js +9 -12
- package/UserMenu/UserMenuLink.js.map +1 -1
- package/UserMenu/UserMenuSeparator.js +9 -9
- package/UserMenu/UserMenuSeparator.js.map +1 -1
- package/UserMenu.js +4 -5
- package/UserMenu.js.map +1 -1
- package/index.js +14 -15
- package/index.js.map +1 -1
- package/package.json +13 -12
- package/static/svg/github.08a73b00.svg +1 -0
- package/static/svg/notFound.e8b15981.svg +1 -0
- package/static/svg/slack.1b2ba162.svg +8 -0
- package/static/svg/x-twitter.46e7218c.svg +5 -0
- package/static/svg/youtube.3c232651.svg +11 -0
- package/Dashboard/components/index.js.map +0 -1
- package/Navigation/SidebarProvider.d.ts +0 -6
- package/Navigation/SidebarProvider.js +0 -34
- package/Navigation/SidebarProvider.js.map +0 -1
- package/Navigation.d.ts +0 -2
- package/Navigation.js +0 -11
- package/Navigation.js.map +0 -1
|
@@ -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,15 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
export interface CommandRow {
|
|
3
|
+
key: string;
|
|
4
|
+
value: string;
|
|
5
|
+
label: string;
|
|
6
|
+
sub?: string;
|
|
7
|
+
icon?: React.ReactNode;
|
|
8
|
+
shortcut?: string[];
|
|
9
|
+
verb: string;
|
|
10
|
+
onRun: () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface CommandGroup {
|
|
13
|
+
title: string;
|
|
14
|
+
rows: CommandRow[];
|
|
15
|
+
}
|
|
File without changes
|
|
@@ -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.js
CHANGED
|
@@ -1,37 +1,33 @@
|
|
|
1
|
-
import
|
|
1
|
+
import react from "react";
|
|
2
2
|
import { Grid, Heading } from "@webiny/admin-ui";
|
|
3
|
-
import { useSecurity } from "@webiny/app-admin";
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
30
|
-
className: "flex flex-col gap-lg"
|
|
31
|
-
}, widgets.filter(w => w.column === "right").map(widget => /*#__PURE__*/React.createElement(React.Fragment, {
|
|
32
|
-
key: widget.name
|
|
33
|
-
}, widget.element))))));
|
|
3
|
+
import { useAdminConfig, useSecurity } from "@webiny/app-admin";
|
|
4
|
+
const Welcome = ()=>{
|
|
5
|
+
const { identity } = useSecurity();
|
|
6
|
+
const { widgets } = useAdminConfig();
|
|
7
|
+
return /*#__PURE__*/ react.createElement("div", {
|
|
8
|
+
className: "my-xxl"
|
|
9
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
10
|
+
className: "mb-3xl"
|
|
11
|
+
}, /*#__PURE__*/ react.createElement(Heading, {
|
|
12
|
+
level: 3
|
|
13
|
+
}, `Hi ${identity.displayName}, what are we doing today?`)), /*#__PURE__*/ react.createElement(Grid, {
|
|
14
|
+
gap: "spacious",
|
|
15
|
+
className: "max-w-[1200px]"
|
|
16
|
+
}, /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
17
|
+
span: 6
|
|
18
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
19
|
+
className: "flex flex-col gap-lg"
|
|
20
|
+
}, widgets.filter((w)=>"left" === w.column).map((widget)=>/*#__PURE__*/ react.createElement(react.Fragment, {
|
|
21
|
+
key: widget.name
|
|
22
|
+
}, widget.element)))), /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
23
|
+
span: 6
|
|
24
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
25
|
+
className: "flex flex-col gap-lg"
|
|
26
|
+
}, widgets.filter((w)=>"right" === w.column).map((widget)=>/*#__PURE__*/ react.createElement(react.Fragment, {
|
|
27
|
+
key: widget.name
|
|
28
|
+
}, widget.element))))));
|
|
34
29
|
};
|
|
35
|
-
|
|
30
|
+
const Dashboard_Welcome = Welcome;
|
|
31
|
+
export default Dashboard_Welcome;
|
|
36
32
|
|
|
37
33
|
//# sourceMappingURL=Welcome.js.map
|
package/Dashboard/Welcome.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"Dashboard/Welcome.js","sources":["../../src/Dashboard/Welcome.tsx"],"sourcesContent":["import React from \"react\";\nimport { Grid, Heading } from \"@webiny/admin-ui\";\nimport { useSecurity } from \"@webiny/app-admin\";\nimport { useAdminConfig } from \"@webiny/app-admin\";\n\nconst Welcome = () => {\n const { identity } = useSecurity();\n const { widgets } = useAdminConfig();\n\n return (\n <div className={\"my-xxl\"}>\n <div className={\"mb-3xl\"}>\n <Heading\n level={3}\n >{`Hi ${identity!.displayName}, what are we doing today?`}</Heading>\n </div>\n <Grid gap={\"spacious\"} className={\"max-w-[1200px]\"}>\n <Grid.Column span={6}>\n <div className={\"flex flex-col gap-lg\"}>\n {widgets\n .filter(w => w.column === \"left\")\n .map(widget => (\n <React.Fragment key={widget.name}>{widget.element}</React.Fragment>\n ))}\n </div>\n </Grid.Column>\n <Grid.Column span={6}>\n <div className={\"flex flex-col gap-lg\"}>\n {widgets\n .filter(w => w.column === \"right\")\n .map(widget => (\n <React.Fragment key={widget.name}>{widget.element}</React.Fragment>\n ))}\n </div>\n </Grid.Column>\n </Grid>\n </div>\n );\n};\n\nexport default Welcome;\n"],"names":["Welcome","identity","useSecurity","widgets","useAdminConfig","Heading","Grid","w","widget","React"],"mappings":";;;AAKA,MAAMA,UAAU;IACZ,MAAM,EAAEC,QAAQ,EAAE,GAAGC;IACrB,MAAM,EAAEC,OAAO,EAAE,GAAGC;IAEpB,OAAO,WAAP,GACI,oBAAC;QAAI,WAAW;qBACZ,oBAAC;QAAI,WAAW;qBACZ,oBAACC,SAAOA;QACJ,OAAO;OACT,CAAC,GAAG,EAAEJ,SAAU,WAAW,CAAC,0BAA0B,CAAC,kBAE7D,oBAACK,MAAIA;QAAC,KAAK;QAAY,WAAW;qBAC9B,oBAACA,KAAK,MAAM;QAAC,MAAM;qBACf,oBAAC;QAAI,WAAW;OACXH,QACI,MAAM,CAACI,CAAAA,IAAKA,AAAa,WAAbA,EAAE,MAAM,EACpB,GAAG,CAACC,CAAAA,SAAAA,WAAAA,GACD,oBAACC,MAAAA,QAAc;YAAC,KAAKD,OAAO,IAAI;WAAGA,OAAO,OAAO,oBAIjE,oBAACF,KAAK,MAAM;QAAC,MAAM;qBACf,oBAAC;QAAI,WAAW;OACXH,QACI,MAAM,CAACI,CAAAA,IAAKA,AAAa,YAAbA,EAAE,MAAM,EACpB,GAAG,CAACC,CAAAA,SAAAA,WAAAA,GACD,oBAACC,MAAAA,QAAc;YAAC,KAAKD,OAAO,IAAI;WAAGA,OAAO,OAAO;AAOjF;AAEA,0BAAeR"}
|
|
@@ -1,55 +1,54 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { ReactComponent
|
|
4
|
-
import { ReactComponent as
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Link, List, Text, Widget } from "@webiny/admin-ui";
|
|
3
|
+
import { ReactComponent } from "@webiny/icons/help_outline.svg";
|
|
4
|
+
import { ReactComponent as arrow_forward_svg_ReactComponent } from "@webiny/icons/arrow_forward.svg";
|
|
5
5
|
import { SimpleLink } from "@webiny/app-admin";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
};
|
|
6
|
+
const AssistanceWidget = ()=>/*#__PURE__*/ react.createElement(Widget, {
|
|
7
|
+
variant: "light",
|
|
8
|
+
title: "Need some assistance?",
|
|
9
|
+
icon: /*#__PURE__*/ react.createElement(Widget.Icon, {
|
|
10
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
11
|
+
label: "Need some assistance?"
|
|
12
|
+
}),
|
|
13
|
+
padding: "md"
|
|
14
|
+
}, /*#__PURE__*/ react.createElement(List, {
|
|
15
|
+
variant: "container",
|
|
16
|
+
className: "flex flex-col gap-y-sm"
|
|
17
|
+
}, /*#__PURE__*/ react.createElement(List.Item, {
|
|
18
|
+
title: "Documentation",
|
|
19
|
+
description: "Explore the Webiny documentation and check out code examples and guides.",
|
|
20
|
+
actions: /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(SimpleLink, {
|
|
21
|
+
to: "https://www.webiny.com/docs",
|
|
22
|
+
target: "_blank",
|
|
23
|
+
rel: "noopener noreferrer"
|
|
24
|
+
}, /*#__PURE__*/ react.createElement(List.Item.Action, {
|
|
25
|
+
icon: /*#__PURE__*/ react.createElement(arrow_forward_svg_ReactComponent, null)
|
|
26
|
+
})))
|
|
27
|
+
}), /*#__PURE__*/ react.createElement(List.Item, {
|
|
28
|
+
title: "Contact us",
|
|
29
|
+
description: /*#__PURE__*/ react.createElement(Text, {
|
|
30
|
+
size: "sm",
|
|
31
|
+
className: "text-neutral-strong"
|
|
32
|
+
}, /*#__PURE__*/ react.createElement(Link, {
|
|
33
|
+
to: "https://www.webiny.com/forms/product-demo",
|
|
34
|
+
target: "_blank",
|
|
35
|
+
rel: "noopener noreferrer",
|
|
36
|
+
variant: "secondary",
|
|
37
|
+
underline: true
|
|
38
|
+
}, "Contact Sales"), ",", " ", /*#__PURE__*/ react.createElement(Link, {
|
|
39
|
+
to: "https://www.webiny.com/partners",
|
|
40
|
+
target: "_blank",
|
|
41
|
+
rel: "noopener noreferrer",
|
|
42
|
+
variant: "secondary",
|
|
43
|
+
underline: true
|
|
44
|
+
}, "Explore Partnerships"), " ", "or", " ", /*#__PURE__*/ react.createElement(Link, {
|
|
45
|
+
to: "https://www.webiny.com/slack",
|
|
46
|
+
target: "_blank",
|
|
47
|
+
rel: "noopener noreferrer",
|
|
48
|
+
variant: "secondary",
|
|
49
|
+
underline: true
|
|
50
|
+
}, "Slack us"), ".")
|
|
51
|
+
})));
|
|
52
|
+
export { AssistanceWidget };
|
|
54
53
|
|
|
55
54
|
//# sourceMappingURL=AssistanceWidget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"Dashboard/components/AssistanceWidget.js","sources":["../../../src/Dashboard/components/AssistanceWidget.tsx"],"sourcesContent":["import React from \"react\";\nimport { Widget, List, Link, Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as HelpIcon } from \"@webiny/icons/help_outline.svg\";\nimport { ReactComponent as ArrowForwardIcon } from \"@webiny/icons/arrow_forward.svg\";\nimport { SimpleLink } from \"@webiny/app-admin\";\n\nexport const AssistanceWidget = () => {\n return (\n <Widget\n variant=\"light\"\n title=\"Need some assistance?\"\n icon={<Widget.Icon icon={<HelpIcon />} label={\"Need some assistance?\"} />}\n padding=\"md\"\n >\n <List variant=\"container\" className=\"flex flex-col gap-y-sm\">\n <List.Item\n title=\"Documentation\"\n description=\"Explore the Webiny documentation and check out code examples and guides.\"\n actions={\n <>\n <SimpleLink\n to=\"https://www.webiny.com/docs\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <List.Item.Action icon={<ArrowForwardIcon />} />\n </SimpleLink>\n </>\n }\n />\n <List.Item\n title=\"Contact us\"\n description={\n <Text size={\"sm\"} className={\"text-neutral-strong\"}>\n <Link\n to={\"https://www.webiny.com/forms/product-demo\"}\n target={\"_blank\"}\n rel={\"noopener noreferrer\"}\n variant={\"secondary\"}\n underline\n >\n Contact Sales\n </Link>\n ,{\" \"}\n <Link\n to={\"https://www.webiny.com/partners\"}\n target={\"_blank\"}\n rel={\"noopener noreferrer\"}\n variant={\"secondary\"}\n underline\n >\n Explore Partnerships\n </Link>{\" \"}\n or{\" \"}\n <Link\n to={\"https://www.webiny.com/slack\"}\n target={\"_blank\"}\n rel={\"noopener noreferrer\"}\n variant={\"secondary\"}\n underline\n >\n Slack us\n </Link>\n .\n </Text>\n }\n />\n </List>\n </Widget>\n );\n};\n"],"names":["AssistanceWidget","Widget","HelpIcon","List","SimpleLink","ArrowForwardIcon","Text","Link"],"mappings":";;;;;AAMO,MAAMA,mBAAmB,IACrB,WAAP,GACI,oBAACC,QAAMA;QACH,SAAQ;QACR,OAAM;QACN,oBAAM,oBAACA,OAAO,IAAI;YAAC,oBAAM,oBAACC,gBAAQA;YAAK,OAAO;;QAC9C,SAAQ;qBAER,oBAACC,MAAIA;QAAC,SAAQ;QAAY,WAAU;qBAChC,oBAACA,KAAK,IAAI;QACN,OAAM;QACN,aAAY;QACZ,uBACI,wDACI,oBAACC,YAAUA;YACP,IAAG;YACH,QAAO;YACP,KAAI;yBAEJ,oBAACD,KAAK,IAAI,CAAC,MAAM;YAAC,oBAAM,oBAACE,kCAAgBA;;sBAKzD,oBAACF,KAAK,IAAI;QACN,OAAM;QACN,2BACI,oBAACG,MAAIA;YAAC,MAAM;YAAM,WAAW;yBACzB,oBAACC,MAAIA;YACD,IAAI;YACJ,QAAQ;YACR,KAAK;YACL,SAAS;YACT;WACH,kBAEM,KACL,mBACF,oBAACA,MAAIA;YACD,IAAI;YACJ,QAAQ;YACR,KAAK;YACL,SAAS;YACT;WACH,yBAEO,KAAI,MACT,mBACH,oBAACA,MAAIA;YACD,IAAI;YACJ,QAAQ;YACR,KAAK;YACL,SAAS;YACT;WACH,aAEM"}
|