@webiny/app-admin-ui 6.6.0-alpha.0 → 6.6.0-alpha.2
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 +10 -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 +14 -0
- package/CommandPalette/usePaletteHotkeys.js +35 -0
- package/CommandPalette/usePaletteHotkeys.js.map +1 -0
- package/Layout.js +6 -2
- package/Layout.js.map +1 -1
- package/package.json +7 -6
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AiChatPresenter } 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 `AiChatPresenter`.
|
|
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: AiChatPresenter.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 your content…",
|
|
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 { AiChatPresenter } 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 `AiChatPresenter`.\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: AiChatPresenter.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 your content…\",\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,YAAuD;QAChF,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,14 @@
|
|
|
1
|
+
import { type CommandPalettePresenter } from "@webiny/app-admin";
|
|
2
|
+
interface PaletteHotkeysParams {
|
|
3
|
+
presenter: CommandPalettePresenter.Interface;
|
|
4
|
+
close: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The palette's global keys: the ones that work while it is closed, or while focus is not in the
|
|
8
|
+
* input. Keys that only mean something while typing stay on the input's `onKeyDown`.
|
|
9
|
+
*
|
|
10
|
+
* Reads the view model during render, so a reactive component calling this still re-renders when
|
|
11
|
+
* the palette opens, a detail view appears, or AI mode is entered.
|
|
12
|
+
*/
|
|
13
|
+
export declare const usePaletteHotkeys: ({ presenter, close }: PaletteHotkeysParams) => void;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
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 })=>{
|
|
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 (!aiModeActive) return void presenter.enterAiMode();
|
|
12
|
+
close();
|
|
13
|
+
},
|
|
14
|
+
backspace: (e)=>{
|
|
15
|
+
if (e.target instanceof HTMLInputElement) return;
|
|
16
|
+
e.preventDefault();
|
|
17
|
+
presenter.cancelCommand();
|
|
18
|
+
},
|
|
19
|
+
...presenter.shortcutKeys
|
|
20
|
+
}), [
|
|
21
|
+
presenter,
|
|
22
|
+
presenter.shortcutKeys,
|
|
23
|
+
isOpen,
|
|
24
|
+
activeCommand,
|
|
25
|
+
aiModeActive,
|
|
26
|
+
close
|
|
27
|
+
]);
|
|
28
|
+
useHotkeys({
|
|
29
|
+
zIndex: PALETTE_HOTKEY_ZINDEX,
|
|
30
|
+
keys
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
export { usePaletteHotkeys };
|
|
34
|
+
|
|
35
|
+
//# 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}\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 }: 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 (!aiModeActive) {\n presenter.enterAiMode();\n return;\n }\n\n close();\n },\n backspace: (e: KeyboardEvent) => {\n if (e.target instanceof HTMLInputElement) {\n return;\n }\n e.preventDefault();\n presenter.cancelCommand();\n },\n ...presenter.shortcutKeys\n }),\n [presenter, presenter.shortcutKeys, isOpen, activeCommand, aiModeActive, close]\n );\n\n useHotkeys({ zIndex: PALETTE_HOTKEY_ZINDEX, keys });\n};\n"],"names":["usePaletteHotkeys","presenter","close","isOpen","activeCommand","aiModeActive","keys","useMemo","e","HTMLInputElement","useHotkeys","PALETTE_HOTKEY_ZINDEX"],"mappings":";;;AAiBO,MAAMA,oBAAoB,CAAC,EAAEC,SAAS,EAAEC,KAAK,EAAwB;IACxE,MAAM,EAAEC,MAAM,EAAEC,aAAa,EAAEC,YAAY,EAAE,GAAGJ,UAAU,EAAE;IAQ5D,MAAMK,OAAOC,QACT,IAAO;YACH,SAAS,CAACC;gBACNA,EAAE,cAAc;gBAEhB,IAAI,CAACL,QAAQ,YACTF,UAAU,IAAI;gBAQlB,IAAIG,eAAe,YACfH,UAAU,aAAa;gBAI3B,IAAI,CAACI,cAAc,YACfJ,UAAU,WAAW;gBAIzBC;YACJ;YACA,WAAW,CAACM;gBACR,IAAIA,EAAE,MAAM,YAAYC,kBACpB;gBAEJD,EAAE,cAAc;gBAChBP,UAAU,aAAa;YAC3B;YACA,GAAGA,UAAU,YAAY;QAC7B,IACA;QAACA;QAAWA,UAAU,YAAY;QAAEE;QAAQC;QAAeC;QAAcH;KAAM;IAGnFQ,WAAW;QAAE,QAAQC;QAAuBL;IAAK;AACrD"}
|
package/Layout.js
CHANGED
|
@@ -3,6 +3,8 @@ import react_helmet from "react-helmet";
|
|
|
3
3
|
import { LayoutRenderer, Navigation, TenantSelector, UserMenu } from "@webiny/app-admin";
|
|
4
4
|
import { HeaderBar, SidebarProvider, cn, useSidebar } from "@webiny/admin-ui";
|
|
5
5
|
import { useLocalStorage, useLocalStorageValue } from "@webiny/app";
|
|
6
|
+
import { CommandPalette } from "./CommandPalette/CommandPalette.js";
|
|
7
|
+
import { Breadcrumbs } from "./Breadcrumbs/Breadcrumbs.js";
|
|
6
8
|
const SIDEBAR_STATE_KEY = "navigation/state";
|
|
7
9
|
const parseSidebarState = (raw)=>{
|
|
8
10
|
try {
|
|
@@ -18,10 +20,12 @@ const LayoutContent = ({ title, startElement = null, hideNavigation = false, chi
|
|
|
18
20
|
};
|
|
19
21
|
return /*#__PURE__*/ react.createElement(react.Fragment, null, title ? /*#__PURE__*/ react.createElement(react_helmet, {
|
|
20
22
|
title: title
|
|
21
|
-
}) : null, hideNavigation ? null : /*#__PURE__*/ react.createElement(Navigation, null), /*#__PURE__*/ react.createElement("div", {
|
|
23
|
+
}) : null, /*#__PURE__*/ react.createElement(CommandPalette, null), hideNavigation ? null : /*#__PURE__*/ react.createElement(Navigation, null), /*#__PURE__*/ react.createElement("div", {
|
|
22
24
|
className: cn("ml-auto bg-neutral-base transition-[max-width,min-width] ease-linear w-full", hideNavigation ? void 0 : widthClassNames)
|
|
23
25
|
}, /*#__PURE__*/ react.createElement(HeaderBar, {
|
|
24
|
-
start:
|
|
26
|
+
start: /*#__PURE__*/ react.createElement("div", {
|
|
27
|
+
className: "flex items-center gap-sm"
|
|
28
|
+
}, /*#__PURE__*/ react.createElement(Breadcrumbs, null), startElement),
|
|
25
29
|
end: /*#__PURE__*/ react.createElement("div", {
|
|
26
30
|
className: "flex gap-x-sm items-center justify-end"
|
|
27
31
|
}, /*#__PURE__*/ react.createElement(TenantSelector, null), /*#__PURE__*/ react.createElement(UserMenu, null))
|
package/Layout.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Layout.js","sources":["../src/Layout.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useRef } from \"react\";\nimport Helmet from \"react-helmet\";\nimport type { LayoutProps } from \"@webiny/app-admin\";\nimport { LayoutRenderer, Navigation, TenantSelector, UserMenu } from \"@webiny/app-admin\";\nimport { HeaderBar, SidebarProvider, cn, useSidebar } from \"@webiny/admin-ui\";\nimport { useLocalStorage, useLocalStorageValue } from \"@webiny/app\";\n\nconst SIDEBAR_STATE_KEY = \"navigation/state\";\n\ntype SidebarCachedState = {\n pinned: boolean;\n expandedSections: string[];\n pinnedItems: string[];\n};\n\nconst parseSidebarState = (raw: unknown): SidebarCachedState | undefined => {\n try {\n if (typeof raw === \"object\" && raw !== null) {\n return raw as SidebarCachedState;\n }\n if (typeof raw === \"string\") {\n return JSON.parse(raw) as SidebarCachedState;\n }\n } catch {\n // Ignore parse errors\n }\n return undefined;\n};\n\nconst LayoutContent = ({\n title,\n startElement = null,\n hideNavigation = false,\n children\n}: LayoutProps) => {\n const { pinned } = useSidebar();\n\n const widthClassNames = {\n \"max-w-[calc(100%-(var(--spacing-sidebar-expanded)))] \": pinned,\n \"max-w-[calc(100%-(var(--spacing-sidebar-collapsed)))] \": !pinned\n };\n\n return (\n <>\n {title ? <Helmet title={title} /> : null}\n {hideNavigation ? null : <Navigation />}\n <div\n className={cn(\n \"ml-auto bg-neutral-base transition-[max-width,min-width] ease-linear w-full\",\n hideNavigation ? undefined : widthClassNames\n )}\n >\n <HeaderBar\n start={startElement}\n end={\n <div className={\"flex gap-x-sm items-center justify-end\"}>\n <TenantSelector />\n <UserMenu />\n </div>\n }\n />\n <main className={\"relative overflow-y-auto h-main-content\"}>{children}</main>\n </div>\n </>\n );\n};\n\nexport const Layout = LayoutRenderer.createDecorator(() => {\n return function Layout(props: LayoutProps) {\n const localStorage = useLocalStorage();\n const localStorageRef = useRef(localStorage);\n localStorageRef.current = localStorage;\n\n const rawState = useLocalStorageValue(SIDEBAR_STATE_KEY);\n const cachedState = useMemo(() => parseSidebarState(rawState), [rawState]);\n\n const onChangeState = useCallback((newState: SidebarCachedState) => {\n localStorageRef.current.set(SIDEBAR_STATE_KEY, JSON.stringify(newState));\n }, []);\n\n return (\n <SidebarProvider state={cachedState} onChangeState={onChangeState}>\n <LayoutContent {...props} />\n </SidebarProvider>\n );\n };\n});\n"],"names":["SIDEBAR_STATE_KEY","parseSidebarState","raw","JSON","LayoutContent","title","startElement","hideNavigation","children","pinned","useSidebar","widthClassNames","Helmet","Navigation","cn","undefined","HeaderBar","TenantSelector","UserMenu","Layout","LayoutRenderer","props","localStorage","useLocalStorage","localStorageRef","useRef","rawState","useLocalStorageValue","cachedState","useMemo","onChangeState","useCallback","newState","SidebarProvider"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Layout.js","sources":["../src/Layout.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useRef } from \"react\";\nimport Helmet from \"react-helmet\";\nimport type { LayoutProps } from \"@webiny/app-admin\";\nimport { LayoutRenderer, Navigation, TenantSelector, UserMenu } from \"@webiny/app-admin\";\nimport { HeaderBar, SidebarProvider, cn, useSidebar } from \"@webiny/admin-ui\";\nimport { useLocalStorage, useLocalStorageValue } from \"@webiny/app\";\nimport { CommandPalette } from \"./CommandPalette/CommandPalette.js\";\nimport { Breadcrumbs } from \"./Breadcrumbs/Breadcrumbs.js\";\n\nconst SIDEBAR_STATE_KEY = \"navigation/state\";\n\ntype SidebarCachedState = {\n pinned: boolean;\n expandedSections: string[];\n pinnedItems: string[];\n};\n\nconst parseSidebarState = (raw: unknown): SidebarCachedState | undefined => {\n try {\n if (typeof raw === \"object\" && raw !== null) {\n return raw as SidebarCachedState;\n }\n if (typeof raw === \"string\") {\n return JSON.parse(raw) as SidebarCachedState;\n }\n } catch {\n // Ignore parse errors\n }\n return undefined;\n};\n\nconst LayoutContent = ({\n title,\n startElement = null,\n hideNavigation = false,\n children\n}: LayoutProps) => {\n const { pinned } = useSidebar();\n\n const widthClassNames = {\n \"max-w-[calc(100%-(var(--spacing-sidebar-expanded)))] \": pinned,\n \"max-w-[calc(100%-(var(--spacing-sidebar-collapsed)))] \": !pinned\n };\n\n return (\n <>\n {title ? <Helmet title={title} /> : null}\n <CommandPalette />\n {hideNavigation ? null : <Navigation />}\n <div\n className={cn(\n \"ml-auto bg-neutral-base transition-[max-width,min-width] ease-linear w-full\",\n hideNavigation ? undefined : widthClassNames\n )}\n >\n <HeaderBar\n start={\n <div className=\"flex items-center gap-sm\">\n <Breadcrumbs />\n {startElement}\n </div>\n }\n end={\n <div className={\"flex gap-x-sm items-center justify-end\"}>\n <TenantSelector />\n <UserMenu />\n </div>\n }\n />\n <main className={\"relative overflow-y-auto h-main-content\"}>{children}</main>\n </div>\n </>\n );\n};\n\nexport const Layout = LayoutRenderer.createDecorator(() => {\n return function Layout(props: LayoutProps) {\n const localStorage = useLocalStorage();\n const localStorageRef = useRef(localStorage);\n localStorageRef.current = localStorage;\n\n const rawState = useLocalStorageValue(SIDEBAR_STATE_KEY);\n const cachedState = useMemo(() => parseSidebarState(rawState), [rawState]);\n\n const onChangeState = useCallback((newState: SidebarCachedState) => {\n localStorageRef.current.set(SIDEBAR_STATE_KEY, JSON.stringify(newState));\n }, []);\n\n return (\n <SidebarProvider state={cachedState} onChangeState={onChangeState}>\n <LayoutContent {...props} />\n </SidebarProvider>\n );\n };\n});\n"],"names":["SIDEBAR_STATE_KEY","parseSidebarState","raw","JSON","LayoutContent","title","startElement","hideNavigation","children","pinned","useSidebar","widthClassNames","Helmet","CommandPalette","Navigation","cn","undefined","HeaderBar","Breadcrumbs","TenantSelector","UserMenu","Layout","LayoutRenderer","props","localStorage","useLocalStorage","localStorageRef","useRef","rawState","useLocalStorageValue","cachedState","useMemo","onChangeState","useCallback","newState","SidebarProvider"],"mappings":";;;;;;;AASA,MAAMA,oBAAoB;AAQ1B,MAAMC,oBAAoB,CAACC;IACvB,IAAI;QACA,IAAI,AAAe,YAAf,OAAOA,OAAoBA,AAAQ,SAARA,KAC3B,OAAOA;QAEX,IAAI,AAAe,YAAf,OAAOA,KACP,OAAOC,KAAK,KAAK,CAACD;IAE1B,EAAE,OAAM,CAER;AAEJ;AAEA,MAAME,gBAAgB,CAAC,EACnBC,KAAK,EACLC,eAAe,IAAI,EACnBC,iBAAiB,KAAK,EACtBC,QAAQ,EACE;IACV,MAAM,EAAEC,MAAM,EAAE,GAAGC;IAEnB,MAAMC,kBAAkB;QACpB,yDAAyDF;QACzD,0DAA0D,CAACA;IAC/D;IAEA,OAAO,WAAP,GACI,0CACKJ,QAAQ,WAARA,GAAQ,oBAACO,cAAMA;QAAC,OAAOP;SAAY,oBACpC,oBAACQ,gBAAcA,OACdN,iBAAiB,OAAO,WAAP,GAAO,oBAACO,YAAUA,OAAAA,WAAAA,GACpC,oBAAC;QACG,WAAWC,GACP,+EACAR,iBAAiBS,SAAYL;qBAGjC,oBAACM,WAASA;QACN,qBACI,oBAAC;YAAI,WAAU;yBACX,oBAACC,aAAWA,OACXZ;QAGT,mBACI,oBAAC;YAAI,WAAW;yBACZ,oBAACa,gBAAcA,OAAAA,WAAAA,GACf,oBAACC,UAAQA;sBAIrB,oBAAC;QAAK,WAAW;OAA4CZ;AAI7E;AAEO,MAAMa,gBAASC,eAAe,eAAe,CAAC,IAC1C,SAAgBC,KAAkB;QACrC,MAAMC,eAAeC;QACrB,MAAMC,kBAAkBC,OAAOH;QAC/BE,gBAAgB,OAAO,GAAGF;QAE1B,MAAMI,WAAWC,qBAAqB7B;QACtC,MAAM8B,cAAcC,QAAQ,IAAM9B,kBAAkB2B,WAAW;YAACA;SAAS;QAEzE,MAAMI,gBAAgBC,YAAY,CAACC;YAC/BR,gBAAgB,OAAO,CAAC,GAAG,CAAC1B,mBAAmBG,KAAK,SAAS,CAAC+B;QAClE,GAAG,EAAE;QAEL,OAAO,WAAP,GACI,oBAACC,iBAAeA;YAAC,OAAOL;YAAa,eAAeE;yBAChD,oBAAC5B,eAAkBmB;IAG/B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app-admin-ui",
|
|
3
|
-
"version": "6.6.0-alpha.
|
|
3
|
+
"version": "6.6.0-alpha.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -14,17 +14,18 @@
|
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@types/react": "18.3.31",
|
|
17
|
-
"@webiny/admin-ui": "6.6.0-alpha.
|
|
18
|
-
"@webiny/app": "6.6.0-alpha.
|
|
19
|
-
"@webiny/app-admin": "6.6.0-alpha.
|
|
20
|
-
"@webiny/icons": "6.6.0-alpha.
|
|
17
|
+
"@webiny/admin-ui": "6.6.0-alpha.2",
|
|
18
|
+
"@webiny/app": "6.6.0-alpha.2",
|
|
19
|
+
"@webiny/app-admin": "6.6.0-alpha.2",
|
|
20
|
+
"@webiny/icons": "6.6.0-alpha.2",
|
|
21
|
+
"cmdk": "1.1.1",
|
|
21
22
|
"react": "18.3.1",
|
|
22
23
|
"react-dom": "18.3.1",
|
|
23
24
|
"react-helmet": "6.1.0"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
27
|
"@types/react-helmet": "6.1.11",
|
|
27
|
-
"@webiny/build-tools": "6.6.0-alpha.
|
|
28
|
+
"@webiny/build-tools": "6.6.0-alpha.2",
|
|
28
29
|
"rimraf": "6.1.3",
|
|
29
30
|
"typescript": "7.0.2"
|
|
30
31
|
},
|