@webiny/app-admin-ui 0.0.0-unstable.7be00a75a9 → 0.0.0-unstable.7c2def32a7
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.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 +50 -21
- package/Layout.js.map +1 -1
- package/index.js +16 -5
- package/index.js.map +1 -1
- package/package.json +15 -8
- package/Navigation/SidebarProvider.d.ts +0 -6
- package/Navigation/SidebarProvider.js +0 -26
- package/Navigation/SidebarProvider.js.map +0 -1
- package/Navigation.d.ts +0 -2
- package/Navigation.js +0 -10
- 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.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;
|
package/Dashboard/Welcome.js
CHANGED
|
@@ -1,32 +1,119 @@
|
|
|
1
|
-
import react from "react";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import react, { useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { DndProvider } from "react-dnd";
|
|
3
|
+
import { HTML5Backend } from "react-dnd-html5-backend";
|
|
4
|
+
import { Heading, Text } from "@webiny/admin-ui";
|
|
5
|
+
import { createReactiveComponent, useAdminConfig, useSecurity } from "@webiny/app-admin";
|
|
6
|
+
import { useDashboardLayoutPresenter } from "./dashboardLayout/presenter/useDashboardLayoutPresenter.js";
|
|
7
|
+
import { toColumnIndex } from "./dashboardLayout/toColumnIndex.js";
|
|
8
|
+
import { AddWidgetDrawer } from "./components/addWidgetDrawer/AddWidgetDrawer.js";
|
|
9
|
+
import { DashboardToolbar } from "./components/DashboardToolbar.js";
|
|
10
|
+
import { EditableColumns } from "./components/layout/EditableColumns.js";
|
|
11
|
+
import { StaticColumns } from "./components/layout/StaticColumns.js";
|
|
12
|
+
import { useColumnsThatFit } from "./components/layout/useColumnsThatFit.js";
|
|
13
|
+
import { useWidgetPortals } from "./components/layout/useWidgetPortals.js";
|
|
14
|
+
import { DASHBOARD_MAX_WIDTH } from "./components/layout/layoutConstants.js";
|
|
15
|
+
const WelcomeBase = ()=>{
|
|
5
16
|
const { identity } = useSecurity();
|
|
6
17
|
const { widgets } = useAdminConfig();
|
|
7
|
-
|
|
8
|
-
|
|
18
|
+
const presenter = useDashboardLayoutPresenter();
|
|
19
|
+
const elements = useMemo(()=>{
|
|
20
|
+
const map = new Map();
|
|
21
|
+
widgets.forEach((widget)=>map.set(widget.name, widget.element));
|
|
22
|
+
return map;
|
|
23
|
+
}, [
|
|
24
|
+
widgets
|
|
25
|
+
]);
|
|
26
|
+
const titles = useMemo(()=>{
|
|
27
|
+
const map = new Map();
|
|
28
|
+
widgets.forEach((widget)=>map.set(widget.name, {
|
|
29
|
+
title: widget.title ?? widget.name
|
|
30
|
+
}));
|
|
31
|
+
return map;
|
|
32
|
+
}, [
|
|
33
|
+
widgets
|
|
34
|
+
]);
|
|
35
|
+
const widgetsKey = widgets.map((w)=>`${w.name}:${toColumnIndex(w.column)}`).join("|");
|
|
36
|
+
useEffect(()=>{
|
|
37
|
+
const inputs = widgets.map((widget)=>({
|
|
38
|
+
name: widget.name,
|
|
39
|
+
column: toColumnIndex(widget.column)
|
|
40
|
+
}));
|
|
41
|
+
presenter.init(identity.id, inputs);
|
|
42
|
+
}, [
|
|
43
|
+
identity?.id,
|
|
44
|
+
widgetsKey
|
|
45
|
+
]);
|
|
46
|
+
useEffect(()=>()=>presenter.dispose(), [
|
|
47
|
+
presenter
|
|
48
|
+
]);
|
|
49
|
+
const { vm } = presenter;
|
|
50
|
+
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
51
|
+
const openDrawer = ()=>setDrawerOpen(true);
|
|
52
|
+
const drawerWidgets = widgets.map((widget)=>{
|
|
53
|
+
const registeredColumn = toColumnIndex(widget.column);
|
|
54
|
+
return {
|
|
55
|
+
name: widget.name,
|
|
56
|
+
title: widget.title ?? widget.name,
|
|
57
|
+
description: widget.description,
|
|
58
|
+
group: widget.group,
|
|
59
|
+
preview: widget.preview,
|
|
60
|
+
added: !vm.hidden.includes(widget.name),
|
|
61
|
+
defaultColumn: Math.min(registeredColumn, vm.columnCount - 1)
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
const { ref: containerRef, visibleCount, allFit } = useColumnsThatFit(vm.columnCount);
|
|
65
|
+
const placed = vm.columns.flat();
|
|
66
|
+
const { slots, portals } = useWidgetPortals(placed, elements);
|
|
67
|
+
const editing = vm.editing && allFit;
|
|
68
|
+
let subtitle = "Your dashboard. Arrange the widgets however you work best.";
|
|
69
|
+
let columns = /*#__PURE__*/ react.createElement(StaticColumns, {
|
|
70
|
+
columns: vm.columns,
|
|
71
|
+
visibleCount: visibleCount,
|
|
72
|
+
slots: slots
|
|
73
|
+
});
|
|
74
|
+
if (editing) {
|
|
75
|
+
subtitle = "Drag widgets to rearrange them, and click Done when you're finished.";
|
|
76
|
+
columns = /*#__PURE__*/ react.createElement(EditableColumns, {
|
|
77
|
+
vm: vm,
|
|
78
|
+
slots: slots,
|
|
79
|
+
titles: titles,
|
|
80
|
+
presenter: presenter,
|
|
81
|
+
onBrowseWidgets: openDrawer
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return /*#__PURE__*/ react.createElement(DndProvider, {
|
|
85
|
+
backend: HTML5Backend
|
|
9
86
|
}, /*#__PURE__*/ react.createElement("div", {
|
|
10
|
-
className: "
|
|
11
|
-
|
|
87
|
+
className: "my-xxl",
|
|
88
|
+
ref: containerRef
|
|
89
|
+
}, portals, /*#__PURE__*/ react.createElement("div", {
|
|
90
|
+
className: "mb-xl flex items-center justify-between gap-lg",
|
|
91
|
+
style: {
|
|
92
|
+
maxWidth: DASHBOARD_MAX_WIDTH
|
|
93
|
+
}
|
|
94
|
+
}, /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement(Heading, {
|
|
12
95
|
level: 3
|
|
13
|
-
}, `Hi ${identity.displayName}, what are we doing today?`)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
96
|
+
}, `Hi ${identity.displayName}, what are we doing today?`), /*#__PURE__*/ react.createElement(Text, {
|
|
97
|
+
as: "div",
|
|
98
|
+
size: "md",
|
|
99
|
+
className: "mt-xs text-neutral-strong"
|
|
100
|
+
}, subtitle)), /*#__PURE__*/ react.createElement("div", {
|
|
101
|
+
className: "flex flex-none items-center gap-sm"
|
|
102
|
+
}, /*#__PURE__*/ react.createElement(DashboardToolbar, {
|
|
103
|
+
vm: vm,
|
|
104
|
+
editing: editing,
|
|
105
|
+
canCustomize: allFit,
|
|
106
|
+
presenter: presenter,
|
|
107
|
+
onAddWidget: openDrawer
|
|
108
|
+
}))), columns, /*#__PURE__*/ react.createElement(AddWidgetDrawer, {
|
|
109
|
+
open: drawerOpen,
|
|
110
|
+
onOpenChange: setDrawerOpen,
|
|
111
|
+
widgets: drawerWidgets,
|
|
112
|
+
columnCount: vm.columnCount,
|
|
113
|
+
presenter: presenter
|
|
114
|
+
})));
|
|
29
115
|
};
|
|
116
|
+
const Welcome = createReactiveComponent(WelcomeBase);
|
|
30
117
|
const Dashboard_Welcome = Welcome;
|
|
31
118
|
export default Dashboard_Welcome;
|
|
32
119
|
|
package/Dashboard/Welcome.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dashboard/Welcome.js","sources":["../../src/Dashboard/Welcome.tsx"],"sourcesContent":["import React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"Dashboard/Welcome.js","sources":["../../src/Dashboard/Welcome.tsx"],"sourcesContent":["import React from \"react\";\nimport { useEffect } from \"react\";\nimport { useMemo } from \"react\";\nimport { useState } from \"react\";\nimport { DndProvider } from \"react-dnd\";\nimport { HTML5Backend } from \"react-dnd-html5-backend\";\nimport { Heading } from \"@webiny/admin-ui\";\nimport { Text } from \"@webiny/admin-ui\";\nimport { useSecurity } from \"@webiny/app-admin\";\nimport { useAdminConfig } from \"@webiny/app-admin\";\nimport { createReactiveComponent } from \"@webiny/app-admin\";\nimport { useDashboardLayoutPresenter } from \"./dashboardLayout/presenter/useDashboardLayoutPresenter.js\";\nimport { toColumnIndex } from \"./dashboardLayout/toColumnIndex.js\";\nimport { AddWidgetDrawer } from \"./components/addWidgetDrawer/AddWidgetDrawer.js\";\nimport type { DrawerWidget } from \"./components/addWidgetDrawer/types.js\";\nimport { DashboardToolbar } from \"./components/DashboardToolbar.js\";\nimport { EditableColumns } from \"./components/layout/EditableColumns.js\";\nimport { StaticColumns } from \"./components/layout/StaticColumns.js\";\nimport { useColumnsThatFit } from \"./components/layout/useColumnsThatFit.js\";\nimport { useWidgetPortals } from \"./components/layout/useWidgetPortals.js\";\nimport { DASHBOARD_MAX_WIDTH } from \"./components/layout/layoutConstants.js\";\n\nconst WelcomeBase = () => {\n const { identity } = useSecurity();\n const { widgets } = useAdminConfig();\n const presenter = useDashboardLayoutPresenter();\n\n // Map of widget name -> React element, so the presenter can deal purely in names.\n const elements = useMemo(() => {\n const map = new Map<string, React.ReactElement>();\n widgets.forEach(widget => map.set(widget.name, widget.element));\n return map;\n }, [widgets]);\n\n // Widget titles, for the cards' labels while customizing.\n const titles = useMemo(() => {\n const map = new Map<string, { title: string }>();\n widgets.forEach(widget => map.set(widget.name, { title: widget.title ?? widget.name }));\n return map;\n }, [widgets]);\n\n // Re-initialize the presenter when the user or the set of registered widgets changes.\n const widgetsKey = widgets.map(w => `${w.name}:${toColumnIndex(w.column)}`).join(\"|\");\n useEffect(() => {\n const inputs = widgets.map(widget => ({\n name: widget.name,\n column: toColumnIndex(widget.column)\n }));\n presenter.init(identity!.id, inputs);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [identity?.id, widgetsKey]);\n\n // The presenter is a singleton; leaving the dashboard resets per-visit state like Customize mode.\n useEffect(() => {\n return () => presenter.dispose();\n }, [presenter]);\n\n // A reactive component re-renders when anything it reads from `vm` changes.\n const { vm } = presenter;\n\n const [drawerOpen, setDrawerOpen] = useState(false);\n const openDrawer = () => setDrawerOpen(true);\n const drawerWidgets: DrawerWidget[] = widgets.map(widget => {\n // Same clamping the presenter applies, so \"(default)\" marks the column it would pick.\n const registeredColumn = toColumnIndex(widget.column);\n return {\n name: widget.name,\n title: widget.title ?? widget.name,\n description: widget.description,\n group: widget.group,\n preview: widget.preview,\n added: !vm.hidden.includes(widget.name),\n defaultColumn: Math.min(registeredColumn, vm.columnCount - 1)\n };\n });\n\n const { ref: containerRef, visibleCount, allFit } = useColumnsThatFit(vm.columnCount);\n const placed = vm.columns.flat();\n const { slots, portals } = useWidgetPortals(placed, elements);\n\n // Customize mode needs every chosen column on screen; too narrow, and it isn't offered.\n const editing = vm.editing && allFit;\n\n let subtitle = \"Your dashboard. Arrange the widgets however you work best.\";\n let columns = <StaticColumns columns={vm.columns} visibleCount={visibleCount} slots={slots} />;\n if (editing) {\n subtitle = \"Drag widgets to rearrange them, and click Done when you're finished.\";\n columns = (\n <EditableColumns\n vm={vm}\n slots={slots}\n titles={titles}\n presenter={presenter}\n onBrowseWidgets={openDrawer}\n />\n );\n }\n\n return (\n <DndProvider backend={HTML5Backend}>\n <div className={\"my-xxl\"} ref={containerRef}>\n {portals}\n <div\n className={\"mb-xl flex items-center justify-between gap-lg\"}\n style={{ maxWidth: DASHBOARD_MAX_WIDTH }}\n >\n <div>\n <Heading\n level={3}\n >{`Hi ${identity!.displayName}, what are we doing today?`}</Heading>\n <Text as={\"div\"} size={\"md\"} className={\"mt-xs text-neutral-strong\"}>\n {subtitle}\n </Text>\n </div>\n <div className={\"flex flex-none items-center gap-sm\"}>\n <DashboardToolbar\n vm={vm}\n editing={editing}\n canCustomize={allFit}\n presenter={presenter}\n onAddWidget={openDrawer}\n />\n </div>\n </div>\n {columns}\n <AddWidgetDrawer\n open={drawerOpen}\n onOpenChange={setDrawerOpen}\n widgets={drawerWidgets}\n columnCount={vm.columnCount}\n presenter={presenter}\n />\n </div>\n </DndProvider>\n );\n};\n\nconst Welcome = createReactiveComponent(WelcomeBase);\n\nexport default Welcome;\n"],"names":["WelcomeBase","identity","useSecurity","widgets","useAdminConfig","presenter","useDashboardLayoutPresenter","elements","useMemo","map","Map","widget","titles","widgetsKey","w","toColumnIndex","useEffect","inputs","vm","drawerOpen","setDrawerOpen","useState","openDrawer","drawerWidgets","registeredColumn","Math","containerRef","visibleCount","allFit","useColumnsThatFit","placed","slots","portals","useWidgetPortals","editing","subtitle","columns","StaticColumns","EditableColumns","DndProvider","HTML5Backend","DASHBOARD_MAX_WIDTH","Heading","Text","DashboardToolbar","AddWidgetDrawer","Welcome","createReactiveComponent"],"mappings":";;;;;;;;;;;;;;AAsBA,MAAMA,cAAc;IAChB,MAAM,EAAEC,QAAQ,EAAE,GAAGC;IACrB,MAAM,EAAEC,OAAO,EAAE,GAAGC;IACpB,MAAMC,YAAYC;IAGlB,MAAMC,WAAWC,QAAQ;QACrB,MAAMC,MAAM,IAAIC;QAChBP,QAAQ,OAAO,CAACQ,CAAAA,SAAUF,IAAI,GAAG,CAACE,OAAO,IAAI,EAAEA,OAAO,OAAO;QAC7D,OAAOF;IACX,GAAG;QAACN;KAAQ;IAGZ,MAAMS,SAASJ,QAAQ;QACnB,MAAMC,MAAM,IAAIC;QAChBP,QAAQ,OAAO,CAACQ,CAAAA,SAAUF,IAAI,GAAG,CAACE,OAAO,IAAI,EAAE;gBAAE,OAAOA,OAAO,KAAK,IAAIA,OAAO,IAAI;YAAC;QACpF,OAAOF;IACX,GAAG;QAACN;KAAQ;IAGZ,MAAMU,aAAaV,QAAQ,GAAG,CAACW,CAAAA,IAAK,GAAGA,EAAE,IAAI,CAAC,CAAC,EAAEC,cAAcD,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC;IACjFE,UAAU;QACN,MAAMC,SAASd,QAAQ,GAAG,CAACQ,CAAAA,SAAW;gBAClC,MAAMA,OAAO,IAAI;gBACjB,QAAQI,cAAcJ,OAAO,MAAM;YACvC;QACAN,UAAU,IAAI,CAACJ,SAAU,EAAE,EAAEgB;IAEjC,GAAG;QAAChB,UAAU;QAAIY;KAAW;IAG7BG,UAAU,IACC,IAAMX,UAAU,OAAO,IAC/B;QAACA;KAAU;IAGd,MAAM,EAAEa,EAAE,EAAE,GAAGb;IAEf,MAAM,CAACc,YAAYC,cAAc,GAAGC,SAAS;IAC7C,MAAMC,aAAa,IAAMF,cAAc;IACvC,MAAMG,gBAAgCpB,QAAQ,GAAG,CAACQ,CAAAA;QAE9C,MAAMa,mBAAmBT,cAAcJ,OAAO,MAAM;QACpD,OAAO;YACH,MAAMA,OAAO,IAAI;YACjB,OAAOA,OAAO,KAAK,IAAIA,OAAO,IAAI;YAClC,aAAaA,OAAO,WAAW;YAC/B,OAAOA,OAAO,KAAK;YACnB,SAASA,OAAO,OAAO;YACvB,OAAO,CAACO,GAAG,MAAM,CAAC,QAAQ,CAACP,OAAO,IAAI;YACtC,eAAec,KAAK,GAAG,CAACD,kBAAkBN,GAAG,WAAW,GAAG;QAC/D;IACJ;IAEA,MAAM,EAAE,KAAKQ,YAAY,EAAEC,YAAY,EAAEC,MAAM,EAAE,GAAGC,kBAAkBX,GAAG,WAAW;IACpF,MAAMY,SAASZ,GAAG,OAAO,CAAC,IAAI;IAC9B,MAAM,EAAEa,KAAK,EAAEC,OAAO,EAAE,GAAGC,iBAAiBH,QAAQvB;IAGpD,MAAM2B,UAAUhB,GAAG,OAAO,IAAIU;IAE9B,IAAIO,WAAW;IACf,IAAIC,UAAU,WAAVA,GAAU,oBAACC,eAAaA;QAAC,SAASnB,GAAG,OAAO;QAAE,cAAcS;QAAc,OAAOI;;IACrF,IAAIG,SAAS;QACTC,WAAW;QACXC,UAAU,WAAVA,GACI,oBAACE,iBAAeA;YACZ,IAAIpB;YACJ,OAAOa;YACP,QAAQnB;YACR,WAAWP;YACX,iBAAiBiB;;IAG7B;IAEA,OAAO,WAAP,GACI,oBAACiB,aAAWA;QAAC,SAASC;qBAClB,oBAAC;QAAI,WAAW;QAAU,KAAKd;OAC1BM,SAAAA,WAAAA,GACD,oBAAC;QACG,WAAW;QACX,OAAO;YAAE,UAAUS;QAAoB;qBAEvC,oBAAC,2BACG,oBAACC,SAAOA;QACJ,OAAO;OACT,CAAC,GAAG,EAAEzC,SAAU,WAAW,CAAC,0BAA0B,CAAC,iBACzD,oBAAC0C,MAAIA;QAAC,IAAI;QAAO,MAAM;QAAM,WAAW;OACnCR,YAAAA,WAAAA,GAGT,oBAAC;QAAI,WAAW;qBACZ,oBAACS,kBAAgBA;QACb,IAAI1B;QACJ,SAASgB;QACT,cAAcN;QACd,WAAWvB;QACX,aAAaiB;UAIxBc,SAAAA,WAAAA,GACD,oBAACS,iBAAeA;QACZ,MAAM1B;QACN,cAAcC;QACd,SAASG;QACT,aAAaL,GAAG,WAAW;QAC3B,WAAWb;;AAK/B;AAEA,MAAMyC,UAAUC,wBAAwB/C;AAExC,0BAAe8C"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { DashboardLayoutPresenter } from "../dashboardLayout/presenter/abstractions.js";
|
|
3
|
+
interface DashboardToolbarProps {
|
|
4
|
+
vm: DashboardLayoutPresenter.ViewModel;
|
|
5
|
+
editing: boolean;
|
|
6
|
+
canCustomize: boolean;
|
|
7
|
+
presenter: DashboardLayoutPresenter.Interface;
|
|
8
|
+
onAddWidget: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const DashboardToolbar: ({ vm, editing, canCustomize, presenter, onAddWidget }: DashboardToolbarProps) => React.JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Button, IconButton, Tooltip } from "@webiny/admin-ui";
|
|
3
|
+
import { ReactComponent } from "@webiny/icons/restart_alt.svg";
|
|
4
|
+
import { ReactComponent as add_svg_ReactComponent } from "@webiny/icons/add.svg";
|
|
5
|
+
import { ReactComponent as dashboard_customize_svg_ReactComponent } from "@webiny/icons/dashboard_customize.svg";
|
|
6
|
+
import { ReactComponent as check_svg_ReactComponent } from "@webiny/icons/check.svg";
|
|
7
|
+
import { ColumnCountControl } from "./dnd/ColumnCountControl.js";
|
|
8
|
+
const DashboardToolbar = ({ vm, editing, canCustomize, presenter, onAddWidget })=>{
|
|
9
|
+
if (editing) return /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(ColumnCountControl, {
|
|
10
|
+
columnCount: vm.columnCount,
|
|
11
|
+
disabled: null !== vm.draggingName,
|
|
12
|
+
presenter: presenter
|
|
13
|
+
}), /*#__PURE__*/ react.createElement(Tooltip, {
|
|
14
|
+
content: "Reset to default layout",
|
|
15
|
+
trigger: /*#__PURE__*/ react.createElement(IconButton, {
|
|
16
|
+
variant: "tertiary",
|
|
17
|
+
size: "md",
|
|
18
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
19
|
+
"aria-label": "Reset to default layout",
|
|
20
|
+
onClick: ()=>presenter.resetToDefault()
|
|
21
|
+
})
|
|
22
|
+
}), /*#__PURE__*/ react.createElement(Button, {
|
|
23
|
+
variant: "tertiary",
|
|
24
|
+
text: "Add widget",
|
|
25
|
+
icon: /*#__PURE__*/ react.createElement(add_svg_ReactComponent, null),
|
|
26
|
+
onClick: onAddWidget
|
|
27
|
+
}), /*#__PURE__*/ react.createElement(Button, {
|
|
28
|
+
variant: "primary",
|
|
29
|
+
text: "Done",
|
|
30
|
+
icon: /*#__PURE__*/ react.createElement(check_svg_ReactComponent, null),
|
|
31
|
+
onClick: ()=>presenter.stopEditing()
|
|
32
|
+
}));
|
|
33
|
+
let hint = "Rearrange, add or remove widgets";
|
|
34
|
+
if (!canCustomize) hint = "Make the window wider to customize the dashboard";
|
|
35
|
+
return /*#__PURE__*/ react.createElement(Tooltip, {
|
|
36
|
+
content: hint,
|
|
37
|
+
trigger: /*#__PURE__*/ react.createElement(Button, {
|
|
38
|
+
variant: "tertiary",
|
|
39
|
+
text: "Customize",
|
|
40
|
+
icon: /*#__PURE__*/ react.createElement(dashboard_customize_svg_ReactComponent, null),
|
|
41
|
+
disabled: !canCustomize,
|
|
42
|
+
onClick: ()=>presenter.startEditing()
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
export { DashboardToolbar };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=DashboardToolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dashboard/components/DashboardToolbar.js","sources":["../../../src/Dashboard/components/DashboardToolbar.tsx"],"sourcesContent":["import React from \"react\";\nimport { Button } from \"@webiny/admin-ui\";\nimport { IconButton } from \"@webiny/admin-ui\";\nimport { Tooltip } from \"@webiny/admin-ui\";\nimport { ReactComponent as RestartAltIcon } from \"@webiny/icons/restart_alt.svg\";\nimport { ReactComponent as AddIcon } from \"@webiny/icons/add.svg\";\nimport { ReactComponent as DashboardCustomizeIcon } from \"@webiny/icons/dashboard_customize.svg\";\nimport { ReactComponent as CheckIcon } from \"@webiny/icons/check.svg\";\nimport { ColumnCountControl } from \"./dnd/ColumnCountControl.js\";\nimport type { DashboardLayoutPresenter } from \"../dashboardLayout/presenter/abstractions.js\";\n\ninterface DashboardToolbarProps {\n vm: DashboardLayoutPresenter.ViewModel;\n // Customize mode is on and every chosen column fits on screen.\n editing: boolean;\n // Every chosen column fits on screen, so Customize mode can be offered.\n canCustomize: boolean;\n presenter: DashboardLayoutPresenter.Interface;\n onAddWidget: () => void;\n}\n\n// Top-right controls: one \"Customize\" button normally, the full editing set in Customize mode.\nexport const DashboardToolbar = ({\n vm,\n editing,\n canCustomize,\n presenter,\n onAddWidget\n}: DashboardToolbarProps) => {\n if (editing) {\n return (\n <>\n <ColumnCountControl\n columnCount={vm.columnCount}\n disabled={vm.draggingName !== null}\n presenter={presenter}\n />\n <Tooltip\n content={\"Reset to default layout\"}\n trigger={\n <IconButton\n variant={\"tertiary\"}\n size={\"md\"}\n icon={<RestartAltIcon />}\n aria-label={\"Reset to default layout\"}\n onClick={() => presenter.resetToDefault()}\n />\n }\n />\n <Button\n variant={\"tertiary\"}\n text={\"Add widget\"}\n icon={<AddIcon />}\n onClick={onAddWidget}\n />\n <Button\n variant={\"primary\"}\n text={\"Done\"}\n icon={<CheckIcon />}\n onClick={() => presenter.stopEditing()}\n />\n </>\n );\n }\n\n let hint = \"Rearrange, add or remove widgets\";\n if (!canCustomize) {\n hint = \"Make the window wider to customize the dashboard\";\n }\n\n return (\n <Tooltip\n content={hint}\n trigger={\n <Button\n variant={\"tertiary\"}\n text={\"Customize\"}\n icon={<DashboardCustomizeIcon />}\n disabled={!canCustomize}\n onClick={() => presenter.startEditing()}\n />\n }\n />\n );\n};\n"],"names":["DashboardToolbar","vm","editing","canCustomize","presenter","onAddWidget","ColumnCountControl","Tooltip","IconButton","RestartAltIcon","Button","AddIcon","CheckIcon","hint","DashboardCustomizeIcon"],"mappings":";;;;;;;AAsBO,MAAMA,mBAAmB,CAAC,EAC7BC,EAAE,EACFC,OAAO,EACPC,YAAY,EACZC,SAAS,EACTC,WAAW,EACS;IACpB,IAAIH,SACA,OAAO,WAAP,GACI,wDACI,oBAACI,oBAAkBA;QACf,aAAaL,GAAG,WAAW;QAC3B,UAAUA,AAAoB,SAApBA,GAAG,YAAY;QACzB,WAAWG;sBAEf,oBAACG,SAAOA;QACJ,SAAS;QACT,uBACI,oBAACC,YAAUA;YACP,SAAS;YACT,MAAM;YACN,oBAAM,oBAACC,gBAAcA;YACrB,cAAY;YACZ,SAAS,IAAML,UAAU,cAAc;;sBAInD,oBAACM,QAAMA;QACH,SAAS;QACT,MAAM;QACN,oBAAM,oBAACC,wBAAOA;QACd,SAASN;sBAEb,oBAACK,QAAMA;QACH,SAAS;QACT,MAAM;QACN,oBAAM,oBAACE,0BAASA;QAChB,SAAS,IAAMR,UAAU,WAAW;;IAMpD,IAAIS,OAAO;IACX,IAAI,CAACV,cACDU,OAAO;IAGX,OAAO,WAAP,GACI,oBAACN,SAAOA;QACJ,SAASM;QACT,uBACI,oBAACH,QAAMA;YACH,SAAS;YACT,MAAM;YACN,oBAAM,oBAACI,wCAAsBA;YAC7B,UAAU,CAACX;YACX,SAAS,IAAMC,UAAU,YAAY;;;AAKzD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { DashboardLayoutPresenter } from "../../dashboardLayout/presenter/abstractions.js";
|
|
3
|
+
import type { DrawerWidget } from "./types.js";
|
|
4
|
+
interface AddToColumnMenuProps {
|
|
5
|
+
widget: DrawerWidget;
|
|
6
|
+
columnCount: number;
|
|
7
|
+
presenter: DashboardLayoutPresenter.Interface;
|
|
8
|
+
}
|
|
9
|
+
export declare const AddToColumnMenu: ({ widget, columnCount, presenter }: AddToColumnMenuProps) => React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Button, DropdownMenu } from "@webiny/admin-ui";
|
|
3
|
+
import { ReactComponent } from "@webiny/icons/expand_more.svg";
|
|
4
|
+
const AddToColumnMenu = ({ widget, columnCount, presenter })=>{
|
|
5
|
+
const columns = Array.from({
|
|
6
|
+
length: columnCount
|
|
7
|
+
}, (_, index)=>index);
|
|
8
|
+
return /*#__PURE__*/ react.createElement(DropdownMenu, {
|
|
9
|
+
trigger: /*#__PURE__*/ react.createElement(Button, {
|
|
10
|
+
size: "sm",
|
|
11
|
+
variant: "tertiary",
|
|
12
|
+
text: "Add",
|
|
13
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
14
|
+
iconPosition: "end"
|
|
15
|
+
})
|
|
16
|
+
}, /*#__PURE__*/ react.createElement(DropdownMenu.Label, {
|
|
17
|
+
text: "Add to"
|
|
18
|
+
}), columns.map((index)=>{
|
|
19
|
+
let text = `Column ${index + 1}`;
|
|
20
|
+
if (index === widget.defaultColumn) text = `${text} (default)`;
|
|
21
|
+
return /*#__PURE__*/ react.createElement(DropdownMenu.Item, {
|
|
22
|
+
key: index,
|
|
23
|
+
text: text,
|
|
24
|
+
onClick: ()=>presenter.addWidget(widget.name, index)
|
|
25
|
+
});
|
|
26
|
+
}));
|
|
27
|
+
};
|
|
28
|
+
export { AddToColumnMenu };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=AddToColumnMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dashboard/components/addWidgetDrawer/AddToColumnMenu.js","sources":["../../../../src/Dashboard/components/addWidgetDrawer/AddToColumnMenu.tsx"],"sourcesContent":["import React from \"react\";\nimport { Button } from \"@webiny/admin-ui\";\nimport { DropdownMenu } from \"@webiny/admin-ui\";\nimport { ReactComponent as ExpandMoreIcon } from \"@webiny/icons/expand_more.svg\";\nimport type { DashboardLayoutPresenter } from \"../../dashboardLayout/presenter/abstractions.js\";\nimport type { DrawerWidget } from \"./types.js\";\n\ninterface AddToColumnMenuProps {\n widget: DrawerWidget;\n columnCount: number;\n presenter: DashboardLayoutPresenter.Interface;\n}\n\n// One item per current column; the widget lands at the bottom of the chosen one.\nexport const AddToColumnMenu = ({ widget, columnCount, presenter }: AddToColumnMenuProps) => {\n const columns = Array.from({ length: columnCount }, (_, index) => index);\n\n return (\n <DropdownMenu\n trigger={\n <Button\n size={\"sm\"}\n variant={\"tertiary\"}\n text={\"Add\"}\n icon={<ExpandMoreIcon />}\n iconPosition={\"end\"}\n />\n }\n >\n <DropdownMenu.Label text={\"Add to\"} />\n {columns.map(index => {\n let text = `Column ${index + 1}`;\n if (index === widget.defaultColumn) {\n text = `${text} (default)`;\n }\n return (\n <DropdownMenu.Item\n key={index}\n text={text}\n onClick={() => presenter.addWidget(widget.name, index)}\n />\n );\n })}\n </DropdownMenu>\n );\n};\n"],"names":["AddToColumnMenu","widget","columnCount","presenter","columns","Array","_","index","DropdownMenu","Button","ExpandMoreIcon","text"],"mappings":";;;AAcO,MAAMA,kBAAkB,CAAC,EAAEC,MAAM,EAAEC,WAAW,EAAEC,SAAS,EAAwB;IACpF,MAAMC,UAAUC,MAAM,IAAI,CAAC;QAAE,QAAQH;IAAY,GAAG,CAACI,GAAGC,QAAUA;IAElE,OAAO,WAAP,GACI,oBAACC,cAAYA;QACT,uBACI,oBAACC,QAAMA;YACH,MAAM;YACN,SAAS;YACT,MAAM;YACN,oBAAM,oBAACC,gBAAcA;YACrB,cAAc;;qBAItB,oBAACF,aAAa,KAAK;QAAC,MAAM;QACzBJ,QAAQ,GAAG,CAACG,CAAAA;QACT,IAAII,OAAO,CAAC,OAAO,EAAEJ,QAAQ,GAAG;QAChC,IAAIA,UAAUN,OAAO,aAAa,EAC9BU,OAAO,GAAGA,KAAK,UAAU,CAAC;QAE9B,OAAO,WAAP,GACI,oBAACH,aAAa,IAAI;YACd,KAAKD;YACL,MAAMI;YACN,SAAS,IAAMR,UAAU,SAAS,CAACF,OAAO,IAAI,EAAEM;;IAG5D;AAGZ"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { DashboardLayoutPresenter } from "../../dashboardLayout/presenter/abstractions.js";
|
|
3
|
+
import type { DrawerWidget } from "./types.js";
|
|
4
|
+
interface AddWidgetDrawerProps {
|
|
5
|
+
open: boolean;
|
|
6
|
+
onOpenChange: (open: boolean) => void;
|
|
7
|
+
widgets: DrawerWidget[];
|
|
8
|
+
columnCount: number;
|
|
9
|
+
presenter: DashboardLayoutPresenter.Interface;
|
|
10
|
+
}
|
|
11
|
+
export declare const AddWidgetDrawer: ({ open, onOpenChange, widgets, columnCount, presenter }: AddWidgetDrawerProps) => React.JSX.Element;
|
|
12
|
+
export {};
|