@webiny/app-admin-ui 0.0.0-unstable.a4637c5ce6 → 0.0.0-unstable.a4f3e4ea8b

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.
Files changed (100) hide show
  1. package/CommandPalette/CommandPalette.d.ts +6 -0
  2. package/CommandPalette/CommandPalette.js +171 -0
  3. package/CommandPalette/CommandPalette.js.map +1 -0
  4. package/CommandPalette/components/CommandDetail.d.ts +13 -0
  5. package/CommandPalette/components/CommandDetail.js +39 -0
  6. package/CommandPalette/components/CommandDetail.js.map +1 -0
  7. package/CommandPalette/components/CommandItemRow.d.ts +5 -0
  8. package/CommandPalette/components/CommandItemRow.js +39 -0
  9. package/CommandPalette/components/CommandItemRow.js.map +1 -0
  10. package/CommandPalette/components/GroupHeading.d.ts +4 -0
  11. package/CommandPalette/components/GroupHeading.js +10 -0
  12. package/CommandPalette/components/GroupHeading.js.map +1 -0
  13. package/CommandPalette/components/HintIcon.d.ts +4 -0
  14. package/CommandPalette/components/HintIcon.js +11 -0
  15. package/CommandPalette/components/HintIcon.js.map +1 -0
  16. package/CommandPalette/components/Kbd.d.ts +4 -0
  17. package/CommandPalette/components/Kbd.js +14 -0
  18. package/CommandPalette/components/Kbd.js.map +1 -0
  19. package/CommandPalette/components/index.d.ts +5 -0
  20. package/CommandPalette/components/index.js +5 -0
  21. package/CommandPalette/constants.d.ts +8 -0
  22. package/CommandPalette/constants.js +5 -0
  23. package/CommandPalette/constants.js.map +1 -0
  24. package/CommandPalette/deriveRows.d.ts +19 -0
  25. package/CommandPalette/deriveRows.js +100 -0
  26. package/CommandPalette/deriveRows.js.map +1 -0
  27. package/CommandPalette/types.d.ts +15 -0
  28. package/CommandPalette/types.js +0 -0
  29. package/Dashboard/Welcome.d.ts +1 -1
  30. package/Dashboard/Welcome.js +29 -44
  31. package/Dashboard/Welcome.js.map +1 -1
  32. package/Dashboard/components/AssistanceWidget.js +52 -57
  33. package/Dashboard/components/AssistanceWidget.js.map +1 -1
  34. package/Dashboard/components/CommunityWidget.js +56 -63
  35. package/Dashboard/components/CommunityWidget.js.map +1 -1
  36. package/Dashboard/components/MissingPermissionsWidget.js +13 -14
  37. package/Dashboard/components/MissingPermissionsWidget.js.map +1 -1
  38. package/Dashboard/components/assets/github.js +14 -0
  39. package/Dashboard/components/assets/github.js.map +1 -0
  40. package/Dashboard/components/assets/slack.js +27 -0
  41. package/Dashboard/components/assets/slack.js.map +1 -0
  42. package/Dashboard/components/assets/x-twitter.js +18 -0
  43. package/Dashboard/components/assets/x-twitter.js.map +1 -0
  44. package/Dashboard/components/assets/youtube.js +28 -0
  45. package/Dashboard/components/assets/youtube.js.map +1 -0
  46. package/Dashboard/components/index.d.ts +3 -4
  47. package/Dashboard/components/index.js +3 -6
  48. package/Dashboard.js +7 -8
  49. package/Dashboard.js.map +1 -1
  50. package/Dialog/DialogContainer.js +55 -67
  51. package/Dialog/DialogContainer.js.map +1 -1
  52. package/Dialog/DialogProvider.js +6 -9
  53. package/Dialog/DialogProvider.js.map +1 -1
  54. package/Dialog.js +6 -10
  55. package/Dialog.js.map +1 -1
  56. package/Layout.js +48 -29
  57. package/Layout.js.map +1 -1
  58. package/Logo.js +12 -13
  59. package/Logo.js.map +1 -1
  60. package/Navigation/Navigation.js +31 -33
  61. package/Navigation/Navigation.js.map +1 -1
  62. package/Navigation/SidebarMenuItems.d.ts +1 -1
  63. package/Navigation/SidebarMenuItems.js +32 -40
  64. package/Navigation/SidebarMenuItems.js.map +1 -1
  65. package/NotFound/notFound.js +297 -0
  66. package/NotFound/notFound.js.map +1 -0
  67. package/NotFound.js +17 -18
  68. package/NotFound.js.map +1 -1
  69. package/README.md +9 -5
  70. package/UserMenu/UserMenu.js +17 -25
  71. package/UserMenu/UserMenu.js.map +1 -1
  72. package/UserMenu/UserMenuHandle.js +33 -42
  73. package/UserMenu/UserMenuHandle.js.map +1 -1
  74. package/UserMenu/UserMenuItem.js +9 -12
  75. package/UserMenu/UserMenuItem.js.map +1 -1
  76. package/UserMenu/UserMenuLink.js +9 -12
  77. package/UserMenu/UserMenuLink.js.map +1 -1
  78. package/UserMenu/UserMenuSeparator.js +9 -9
  79. package/UserMenu/UserMenuSeparator.js.map +1 -1
  80. package/UserMenu.js +8 -9
  81. package/UserMenu.js.map +1 -1
  82. package/index.js +22 -11
  83. package/index.js.map +1 -1
  84. package/package.json +21 -25
  85. package/static/svg/github.08a73b00.svg +1 -0
  86. package/static/svg/notFound.e8b15981.svg +1 -0
  87. package/static/svg/slack.1b2ba162.svg +8 -0
  88. package/static/svg/x-twitter.46e7218c.svg +5 -0
  89. package/static/svg/youtube.3c232651.svg +11 -0
  90. package/styles.scss +1 -1
  91. package/Dashboard/components/ApplicationWidget.d.ts +0 -9
  92. package/Dashboard/components/ApplicationWidget.js +0 -31
  93. package/Dashboard/components/ApplicationWidget.js.map +0 -1
  94. package/Dashboard/components/index.js.map +0 -1
  95. package/Navigation/SidebarProvider.d.ts +0 -6
  96. package/Navigation/SidebarProvider.js +0 -9
  97. package/Navigation/SidebarProvider.js.map +0 -1
  98. package/Navigation.d.ts +0 -2
  99. package/Navigation.js +0 -11
  100. package/Navigation.js.map +0 -1
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ declare const CommandPaletteBase: () => React.JSX.Element | null;
3
+ export declare const CommandPalette: typeof CommandPaletteBase & {
4
+ displayName: string;
5
+ };
6
+ export {};
@@ -0,0 +1,171 @@
1
+ import react, { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { Command } from "cmdk";
3
+ import { CommandPaletteFeature, createReactiveComponent, useAdminConfig, useHotkeys } from "@webiny/app-admin";
4
+ import { useContainer, useFeature } from "@webiny/app";
5
+ import { RouterGateway } from "@webiny/app/features/router/abstractions.js";
6
+ import { EmptyState, Icon, Text } from "@webiny/admin-ui";
7
+ import { ReactComponent } from "@webiny/icons/search.svg";
8
+ import { ReactComponent as keyboard_return_svg_ReactComponent } from "@webiny/icons/keyboard_return.svg";
9
+ import { ReactComponent as keyboard_arrow_up_svg_ReactComponent } from "@webiny/icons/keyboard_arrow_up.svg";
10
+ import { ReactComponent as keyboard_arrow_down_svg_ReactComponent } from "@webiny/icons/keyboard_arrow_down.svg";
11
+ import { NAVIGATION_GROUP, PALETTE_HOTKEY_ZINDEX } from "./constants.js";
12
+ import { commandVmsToGroups, deriveNavigationRows } from "./deriveRows.js";
13
+ import { CommandDetail, CommandItemRow, GroupHeading, HintIcon, Kbd } from "./components/index.js";
14
+ const CommandPaletteBase = ()=>{
15
+ const [query, setQuery] = useState("");
16
+ const { presenter } = useFeature(CommandPaletteFeature);
17
+ const { menus } = useAdminConfig();
18
+ const container = useContainer();
19
+ const { vm } = presenter;
20
+ useEffect(()=>{
21
+ presenter.init();
22
+ }, [
23
+ presenter
24
+ ]);
25
+ const close = useCallback(()=>{
26
+ presenter.close();
27
+ setQuery("");
28
+ }, [
29
+ presenter
30
+ ]);
31
+ const navigateTo = useCallback((to)=>{
32
+ container.resolve(RouterGateway).pushState(to);
33
+ close();
34
+ }, [
35
+ container,
36
+ close
37
+ ]);
38
+ const runCommand = useCallback((name)=>presenter.useCommand(name), [
39
+ presenter
40
+ ]);
41
+ const keys = useMemo(()=>({
42
+ "mod+k": (e)=>{
43
+ e.preventDefault();
44
+ presenter.toggle();
45
+ setQuery("");
46
+ },
47
+ backspace: (e)=>{
48
+ if (!presenter.vm.isOpen) return;
49
+ const target = e.target;
50
+ if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLElement && target.isContentEditable) return;
51
+ e.preventDefault();
52
+ presenter.cancelCommand();
53
+ },
54
+ ...presenter.shortcutKeys
55
+ }), [
56
+ presenter,
57
+ presenter.shortcutKeys
58
+ ]);
59
+ useHotkeys({
60
+ zIndex: PALETTE_HOTKEY_ZINDEX,
61
+ keys
62
+ });
63
+ const groups = useMemo(()=>{
64
+ const result = [];
65
+ const navigationRows = deriveNavigationRows(menus, navigateTo);
66
+ if (navigationRows.length > 0) result.push({
67
+ title: NAVIGATION_GROUP,
68
+ rows: navigationRows
69
+ });
70
+ result.push(...commandVmsToGroups(vm.commands, runCommand));
71
+ return result;
72
+ }, [
73
+ menus,
74
+ vm.commands,
75
+ navigateTo,
76
+ runCommand
77
+ ]);
78
+ if (!vm.isOpen) return null;
79
+ const active = vm.activeCommand;
80
+ const onKeyDown = (e)=>{
81
+ if ("Escape" === e.key) {
82
+ e.preventDefault();
83
+ if (active) presenter.cancelCommand();
84
+ else close();
85
+ }
86
+ };
87
+ return /*#__PURE__*/ react.createElement("div", {
88
+ role: "presentation",
89
+ onClick: close,
90
+ className: "fixed inset-0 z-overlay flex items-start justify-center bg-neutral-dark/50",
91
+ style: {
92
+ padding: "13vh 16px 16px",
93
+ backdropFilter: "blur(2px)"
94
+ }
95
+ }, /*#__PURE__*/ react.createElement("div", {
96
+ onClick: (e)=>e.stopPropagation(),
97
+ onKeyDown: onKeyDown,
98
+ className: "flex w-full flex-col overflow-hidden rounded-lg border border-neutral-dimmed bg-neutral-base shadow-xxl",
99
+ style: {
100
+ maxWidth: 660,
101
+ height: "45vh"
102
+ }
103
+ }, active ? /*#__PURE__*/ react.createElement(CommandDetail, {
104
+ active: active,
105
+ onBack: ()=>presenter.cancelCommand(),
106
+ onClose: close
107
+ }) : /*#__PURE__*/ react.createElement(Command, {
108
+ label: "Command palette",
109
+ style: {
110
+ display: "flex",
111
+ flexDirection: "column",
112
+ flex: 1,
113
+ minHeight: 0
114
+ }
115
+ }, /*#__PURE__*/ react.createElement("div", {
116
+ className: "flex items-center gap-sm border-b border-neutral-subtle px-md py-sm-plus"
117
+ }, /*#__PURE__*/ react.createElement(Icon, {
118
+ icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
119
+ color: "neutral-light",
120
+ size: "md",
121
+ label: "Search"
122
+ }), /*#__PURE__*/ react.createElement(Command.Input, {
123
+ autoFocus: true,
124
+ value: query,
125
+ onValueChange: setQuery,
126
+ spellCheck: false,
127
+ placeholder: "Search for pages and actions…",
128
+ className: "min-w-0 flex-1 border-0 bg-transparent text-lg text-neutral-primary outline-none"
129
+ }), /*#__PURE__*/ react.createElement(Kbd, null, "esc")), /*#__PURE__*/ react.createElement(Command.List, {
130
+ className: "p-xs-plus",
131
+ style: {
132
+ flex: 1,
133
+ minHeight: 0,
134
+ overflowY: "auto"
135
+ }
136
+ }, /*#__PURE__*/ react.createElement(Command.Empty, null, /*#__PURE__*/ react.createElement(EmptyState, {
137
+ type: "select",
138
+ title: `No results for “${query}”`,
139
+ description: "Try a page name, or an action like “new entry”."
140
+ })), groups.map((group)=>/*#__PURE__*/ react.createElement(Command.Group, {
141
+ key: group.title,
142
+ heading: /*#__PURE__*/ react.createElement(GroupHeading, {
143
+ title: group.title
144
+ })
145
+ }, group.rows.map((row)=>/*#__PURE__*/ react.createElement(CommandItemRow, {
146
+ key: row.key,
147
+ row: row
148
+ })))))), /*#__PURE__*/ react.createElement("div", {
149
+ className: "flex items-center justify-between gap-sm border-t border-neutral-subtle bg-neutral-subtle px-sm py-xs-plus text-neutral-muted"
150
+ }, /*#__PURE__*/ react.createElement(Text, {
151
+ size: "sm"
152
+ }, "Webiny command palette"), /*#__PURE__*/ react.createElement("div", {
153
+ className: "flex items-center gap-md"
154
+ }, /*#__PURE__*/ react.createElement(Text, {
155
+ size: "sm",
156
+ className: "inline-flex items-center gap-xs"
157
+ }, /*#__PURE__*/ react.createElement(Kbd, null, /*#__PURE__*/ react.createElement(HintIcon, {
158
+ element: /*#__PURE__*/ react.createElement(keyboard_arrow_up_svg_ReactComponent, null)
159
+ }), /*#__PURE__*/ react.createElement(HintIcon, {
160
+ element: /*#__PURE__*/ react.createElement(keyboard_arrow_down_svg_ReactComponent, null)
161
+ })), "Navigate"), /*#__PURE__*/ react.createElement(Text, {
162
+ size: "sm",
163
+ className: "inline-flex items-center gap-xs"
164
+ }, /*#__PURE__*/ react.createElement(Kbd, null, /*#__PURE__*/ react.createElement(HintIcon, {
165
+ element: /*#__PURE__*/ react.createElement(keyboard_return_svg_ReactComponent, null)
166
+ })), "Select")))));
167
+ };
168
+ const CommandPalette = createReactiveComponent(CommandPaletteBase);
169
+ export { CommandPalette };
170
+
171
+ //# sourceMappingURL=CommandPalette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette/CommandPalette.js","sources":["../../src/CommandPalette/CommandPalette.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { Command } from \"cmdk\";\nimport {\n CommandPaletteFeature,\n createReactiveComponent,\n useAdminConfig,\n useHotkeys\n} from \"@webiny/app-admin\";\nimport { useContainer, useFeature } from \"@webiny/app\";\nimport { RouterGateway } from \"@webiny/app/features/router/abstractions.js\";\nimport { EmptyState, Icon, Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as SearchIcon } from \"@webiny/icons/search.svg\";\nimport { ReactComponent as ReturnIcon } from \"@webiny/icons/keyboard_return.svg\";\nimport { ReactComponent as ArrowUpIcon } from \"@webiny/icons/keyboard_arrow_up.svg\";\nimport { ReactComponent as ArrowDownIcon } from \"@webiny/icons/keyboard_arrow_down.svg\";\nimport { NAVIGATION_GROUP, PALETTE_HOTKEY_ZINDEX } from \"./constants.js\";\nimport type { CommandGroup } from \"./types.js\";\nimport { commandVmsToGroups, deriveNavigationRows } from \"./deriveRows.js\";\nimport { CommandDetail, CommandItemRow, GroupHeading, HintIcon, Kbd } from \"./components/index.js\";\n\nconst CommandPaletteBase = () => {\n const [query, setQuery] = useState(\"\");\n const { presenter } = useFeature(CommandPaletteFeature);\n const { menus } = useAdminConfig();\n const container = useContainer();\n const { vm } = presenter;\n\n useEffect(() => {\n presenter.init();\n }, [presenter]);\n\n const close = useCallback(() => {\n presenter.close();\n setQuery(\"\");\n }, [presenter]);\n\n const navigateTo = useCallback(\n (to: string) => {\n container.resolve(RouterGateway).pushState(to);\n close();\n },\n [container, close]\n );\n\n const runCommand = useCallback((name: string) => presenter.useCommand(name), [presenter]);\n\n // mod+k toggles; backspace backs out of a detail view; command shortcuts run directly.\n const keys = useMemo(\n () => ({\n \"mod+k\": (e: KeyboardEvent) => {\n e.preventDefault();\n presenter.toggle();\n setQuery(\"\");\n },\n backspace: (e: KeyboardEvent) => {\n // This is a global (document-level) handler, so only act while the palette\n // is actually open — otherwise it would swallow Backspace everywhere.\n if (!presenter.vm.isOpen) {\n return;\n }\n // Never intercept Backspace while the user is editing text: <input>,\n // <textarea>, or any contentEditable (e.g. rich-text/lexical) element.\n const target = e.target;\n if (\n target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n (target instanceof HTMLElement && target.isContentEditable)\n ) {\n return;\n }\n e.preventDefault();\n presenter.cancelCommand();\n },\n ...presenter.shortcutKeys\n }),\n [presenter, presenter.shortcutKeys]\n );\n\n useHotkeys({ zIndex: PALETTE_HOTKEY_ZINDEX, keys });\n\n const groups = useMemo<CommandGroup[]>(() => {\n const result: CommandGroup[] = [];\n const navigationRows = deriveNavigationRows(menus, navigateTo);\n if (navigationRows.length > 0) {\n result.push({ title: NAVIGATION_GROUP, rows: navigationRows });\n }\n result.push(...commandVmsToGroups(vm.commands, runCommand));\n return result;\n }, [menus, vm.commands, navigateTo, runCommand]);\n\n if (!vm.isOpen) {\n return null;\n }\n\n const active = vm.activeCommand;\n\n const onKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n if (active) {\n presenter.cancelCommand();\n } else {\n close();\n }\n }\n };\n\n return (\n <div\n role=\"presentation\"\n onClick={close}\n className=\"fixed inset-0 z-overlay flex items-start justify-center bg-neutral-dark/50\"\n style={{ padding: \"13vh 16px 16px\", backdropFilter: \"blur(2px)\" }}\n >\n <div\n onClick={e => e.stopPropagation()}\n onKeyDown={onKeyDown}\n className=\"flex w-full flex-col overflow-hidden rounded-lg border border-neutral-dimmed bg-neutral-base shadow-xxl\"\n style={{ maxWidth: 660, height: \"45vh\" }}\n >\n {active ? (\n <CommandDetail\n active={active}\n onBack={() => presenter.cancelCommand()}\n onClose={close}\n />\n ) : (\n <Command\n label=\"Command palette\"\n style={{ display: \"flex\", flexDirection: \"column\", flex: 1, minHeight: 0 }}\n >\n <div className=\"flex items-center gap-sm border-b border-neutral-subtle px-md py-sm-plus\">\n <Icon\n icon={<SearchIcon />}\n color={\"neutral-light\"}\n size={\"md\"}\n label={\"Search\"}\n />\n <Command.Input\n autoFocus\n value={query}\n onValueChange={setQuery}\n spellCheck={false}\n placeholder=\"Search for pages and actions…\"\n className=\"min-w-0 flex-1 border-0 bg-transparent text-lg text-neutral-primary outline-none\"\n />\n <Kbd>esc</Kbd>\n </div>\n\n <Command.List\n className=\"p-xs-plus\"\n style={{ flex: 1, minHeight: 0, overflowY: \"auto\" }}\n >\n <Command.Empty>\n <EmptyState\n type=\"select\"\n title={`No results for “${query}”`}\n description=\"Try a page name, or an action like “new entry”.\"\n />\n </Command.Empty>\n\n {groups.map(group => (\n <Command.Group\n key={group.title}\n heading={<GroupHeading title={group.title} />}\n >\n {group.rows.map(row => (\n <CommandItemRow key={row.key} row={row} />\n ))}\n </Command.Group>\n ))}\n </Command.List>\n </Command>\n )}\n\n <div className=\"flex items-center justify-between gap-sm border-t border-neutral-subtle bg-neutral-subtle px-sm py-xs-plus text-neutral-muted\">\n <Text size=\"sm\">Webiny command palette</Text>\n <div className=\"flex items-center gap-md\">\n <Text size=\"sm\" className=\"inline-flex items-center gap-xs\">\n <Kbd>\n <HintIcon element={<ArrowUpIcon />} />\n <HintIcon element={<ArrowDownIcon />} />\n </Kbd>\n Navigate\n </Text>\n <Text size=\"sm\" className=\"inline-flex items-center gap-xs\">\n <Kbd>\n <HintIcon element={<ReturnIcon />} />\n </Kbd>\n Select\n </Text>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport const CommandPalette = createReactiveComponent(CommandPaletteBase);\n"],"names":["CommandPaletteBase","query","setQuery","useState","presenter","useFeature","CommandPaletteFeature","menus","useAdminConfig","container","useContainer","vm","useEffect","close","useCallback","navigateTo","to","RouterGateway","runCommand","name","keys","useMemo","e","target","HTMLInputElement","HTMLTextAreaElement","HTMLElement","useHotkeys","PALETTE_HOTKEY_ZINDEX","groups","result","navigationRows","deriveNavigationRows","NAVIGATION_GROUP","commandVmsToGroups","active","onKeyDown","CommandDetail","Command","Icon","SearchIcon","Kbd","EmptyState","group","GroupHeading","row","CommandItemRow","Text","HintIcon","ArrowUpIcon","ArrowDownIcon","ReturnIcon","CommandPalette","createReactiveComponent"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import type { ActiveCommandVm } from "@webiny/app-admin";
3
+ interface CommandDetailProps {
4
+ active: ActiveCommandVm;
5
+ onBack: () => void;
6
+ onClose: () => void;
7
+ }
8
+ /**
9
+ * Renders a command's detail view (e.g. a form) inside the palette. Back returns to the
10
+ * command list; the detail view itself calls onClose when it completes.
11
+ */
12
+ export declare const CommandDetail: ({ active, onBack, onClose }: CommandDetailProps) => React.JSX.Element;
13
+ export {};
@@ -0,0 +1,39 @@
1
+ import react from "react";
2
+ import { IconButton, Text } from "@webiny/admin-ui";
3
+ import { ReactComponent } from "@webiny/icons/arrow_back.svg";
4
+ import { Kbd } from "./Kbd.js";
5
+ const CommandDetail = ({ active, onBack, onClose })=>{
6
+ const { command, DetailView } = active;
7
+ return /*#__PURE__*/ react.createElement("div", {
8
+ style: {
9
+ display: "flex",
10
+ flexDirection: "column",
11
+ flex: 1,
12
+ minHeight: 0
13
+ }
14
+ }, /*#__PURE__*/ react.createElement("div", {
15
+ className: "flex items-center gap-sm border-b border-neutral-subtle px-md py-sm-plus"
16
+ }, /*#__PURE__*/ react.createElement(IconButton, {
17
+ variant: "ghost",
18
+ size: "sm",
19
+ icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
20
+ onClick: onBack,
21
+ "aria-label": "Back"
22
+ }), command.icon, /*#__PURE__*/ react.createElement(Text, {
23
+ size: "md",
24
+ className: "flex-1 font-medium text-neutral-primary"
25
+ }, command.label), /*#__PURE__*/ react.createElement(Kbd, null, "esc")), /*#__PURE__*/ react.createElement("div", {
26
+ style: {
27
+ flex: 1,
28
+ minHeight: 0,
29
+ overflowY: "auto"
30
+ }
31
+ }, /*#__PURE__*/ react.createElement(DetailView, {
32
+ command: command,
33
+ onClose: onClose,
34
+ onBack: onBack
35
+ })));
36
+ };
37
+ export { CommandDetail };
38
+
39
+ //# sourceMappingURL=CommandDetail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette/components/CommandDetail.js","sources":["../../../src/CommandPalette/components/CommandDetail.tsx"],"sourcesContent":["import React from \"react\";\nimport { IconButton, Text } from \"@webiny/admin-ui\";\nimport type { ActiveCommandVm } from \"@webiny/app-admin\";\nimport { ReactComponent as BackIcon } from \"@webiny/icons/arrow_back.svg\";\nimport { Kbd } from \"./Kbd.js\";\n\ninterface CommandDetailProps {\n active: ActiveCommandVm;\n onBack: () => void;\n onClose: () => void;\n}\n\n/**\n * Renders a command's detail view (e.g. a form) inside the palette. Back returns to the\n * command list; the detail view itself calls onClose when it completes.\n */\nexport const CommandDetail = ({ active, onBack, onClose }: CommandDetailProps) => {\n const { command, DetailView } = active;\n\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", flex: 1, minHeight: 0 }}>\n <div className=\"flex items-center gap-sm border-b border-neutral-subtle px-md py-sm-plus\">\n <IconButton\n variant={\"ghost\"}\n size={\"sm\"}\n icon={<BackIcon />}\n onClick={onBack}\n aria-label=\"Back\"\n />\n {command.icon}\n <Text size=\"md\" className=\"flex-1 font-medium text-neutral-primary\">\n {command.label}\n </Text>\n <Kbd>esc</Kbd>\n </div>\n <div style={{ flex: 1, minHeight: 0, overflowY: \"auto\" }}>\n <DetailView command={command} onClose={onClose} onBack={onBack} />\n </div>\n </div>\n );\n};\n"],"names":["CommandDetail","active","onBack","onClose","command","DetailView","IconButton","BackIcon","Text","Kbd"],"mappings":";;;;AAgBO,MAAMA,gBAAgB,CAAC,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAsB;IACzE,MAAM,EAAEC,OAAO,EAAEC,UAAU,EAAE,GAAGJ;IAEhC,OAAO,WAAP,GACI,oBAAC;QAAI,OAAO;YAAE,SAAS;YAAQ,eAAe;YAAU,MAAM;YAAG,WAAW;QAAE;qBAC1E,oBAAC;QAAI,WAAU;qBACX,oBAACK,YAAUA;QACP,SAAS;QACT,MAAM;QACN,oBAAM,oBAACC,gBAAQA;QACf,SAASL;QACT,cAAW;QAEdE,QAAQ,IAAI,gBACb,oBAACI,MAAIA;QAAC,MAAK;QAAK,WAAU;OACrBJ,QAAQ,KAAK,iBAElB,oBAACK,KAAGA,MAAC,uBAET,oBAAC;QAAI,OAAO;YAAE,MAAM;YAAG,WAAW;YAAG,WAAW;QAAO;qBACnD,oBAACJ,YAAAA;QAAW,SAASD;QAAS,SAASD;QAAS,QAAQD;;AAIxE"}
@@ -0,0 +1,5 @@
1
+ import React from "react";
2
+ import type { CommandRow } from "../types.js";
3
+ export declare const CommandItemRow: ({ row }: {
4
+ row: CommandRow;
5
+ }) => React.JSX.Element;
@@ -0,0 +1,39 @@
1
+ import react from "react";
2
+ import { Command, useCommandState } from "cmdk";
3
+ import { Icon, Text } from "@webiny/admin-ui";
4
+ import { ReactComponent } from "@webiny/icons/keyboard_return.svg";
5
+ import { Kbd } from "./Kbd.js";
6
+ const CommandItemRow = ({ row })=>{
7
+ const selected = useCommandState((state)=>(state.value || "") === row.value);
8
+ return /*#__PURE__*/ react.createElement(Command.Item, {
9
+ value: row.value,
10
+ onSelect: row.onRun,
11
+ className: "flex cursor-pointer items-center gap-sm rounded-md px-sm py-xs-plus data-[selected=true]:bg-neutral-dimmed"
12
+ }, /*#__PURE__*/ react.createElement("div", {
13
+ className: "grid size-xl shrink-0 place-items-center rounded-md border " + (selected ? "border-primary bg-primary-subtle" : "border-neutral-dimmed bg-neutral-subtle")
14
+ }, row.icon ?? null), /*#__PURE__*/ react.createElement("div", {
15
+ className: "min-w-0 flex-1"
16
+ }, /*#__PURE__*/ react.createElement(Text, {
17
+ as: "div",
18
+ size: "md",
19
+ className: "truncate font-medium text-neutral-primary"
20
+ }, row.label), row.sub ? /*#__PURE__*/ react.createElement(Text, {
21
+ as: "div",
22
+ size: "sm",
23
+ className: "truncate text-neutral-muted"
24
+ }, row.sub) : null), /*#__PURE__*/ react.createElement("div", {
25
+ className: "ml-auto flex shrink-0 items-center gap-xs"
26
+ }, row.shortcut?.map((key, index)=>/*#__PURE__*/ react.createElement(Kbd, {
27
+ key: index
28
+ }, key)), selected ? /*#__PURE__*/ react.createElement("span", {
29
+ className: "inline-flex items-center gap-xs rounded-sm bg-primary px-xs py-xs text-sm font-medium text-neutral-base"
30
+ }, row.verb, /*#__PURE__*/ react.createElement(Icon, {
31
+ icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
32
+ color: "neutral-base",
33
+ size: "xs",
34
+ label: ""
35
+ })) : null));
36
+ };
37
+ export { CommandItemRow };
38
+
39
+ //# sourceMappingURL=CommandItemRow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette/components/CommandItemRow.js","sources":["../../../src/CommandPalette/components/CommandItemRow.tsx"],"sourcesContent":["import React from \"react\";\nimport { Command, useCommandState } from \"cmdk\";\nimport { Icon, Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as ReturnIcon } from \"@webiny/icons/keyboard_return.svg\";\nimport type { CommandRow } from \"../types.js\";\nimport { Kbd } from \"./Kbd.js\";\n\nexport const CommandItemRow = ({ row }: { row: CommandRow }) => {\n const selected = useCommandState(state => (state.value || \"\") === row.value);\n\n return (\n <Command.Item\n value={row.value}\n onSelect={row.onRun}\n className=\"flex cursor-pointer items-center gap-sm rounded-md px-sm py-xs-plus data-[selected=true]:bg-neutral-dimmed\"\n >\n <div\n className={\n \"grid size-xl shrink-0 place-items-center rounded-md border \" +\n (selected\n ? \"border-primary bg-primary-subtle\"\n : \"border-neutral-dimmed bg-neutral-subtle\")\n }\n >\n {row.icon ?? null}\n </div>\n <div className=\"min-w-0 flex-1\">\n <Text as=\"div\" size=\"md\" className=\"truncate font-medium text-neutral-primary\">\n {row.label}\n </Text>\n {row.sub ? (\n <Text as=\"div\" size=\"sm\" className=\"truncate text-neutral-muted\">\n {row.sub}\n </Text>\n ) : null}\n </div>\n <div className=\"ml-auto flex shrink-0 items-center gap-xs\">\n {row.shortcut?.map((key, index) => (\n <Kbd key={index}>{key}</Kbd>\n ))}\n {selected ? (\n <span className=\"inline-flex items-center gap-xs rounded-sm bg-primary px-xs py-xs text-sm font-medium text-neutral-base\">\n {row.verb}\n <Icon icon={<ReturnIcon />} color={\"neutral-base\"} size={\"xs\"} label={\"\"} />\n </span>\n ) : null}\n </div>\n </Command.Item>\n );\n};\n"],"names":["CommandItemRow","row","selected","useCommandState","state","Command","Text","key","index","Kbd","Icon","ReturnIcon"],"mappings":";;;;;AAOO,MAAMA,iBAAiB,CAAC,EAAEC,GAAG,EAAuB;IACvD,MAAMC,WAAWC,gBAAgBC,CAAAA,QAAUA,AAAAA,CAAAA,MAAM,KAAK,IAAI,EAAC,MAAOH,IAAI,KAAK;IAE3E,OAAO,WAAP,GACI,oBAACI,QAAQ,IAAI;QACT,OAAOJ,IAAI,KAAK;QAChB,UAAUA,IAAI,KAAK;QACnB,WAAU;qBAEV,oBAAC;QACG,WACI,gEACCC,CAAAA,WACK,qCACA,yCAAwC;OAGjDD,IAAI,IAAI,IAAI,qBAEjB,oBAAC;QAAI,WAAU;qBACX,oBAACK,MAAIA;QAAC,IAAG;QAAM,MAAK;QAAK,WAAU;OAC9BL,IAAI,KAAK,GAEbA,IAAI,GAAG,GAAG,WAAH,GACJ,oBAACK,MAAIA;QAAC,IAAG;QAAM,MAAK;QAAK,WAAU;OAC9BL,IAAI,GAAG,IAEZ,qBAER,oBAAC;QAAI,WAAU;OACVA,IAAI,QAAQ,EAAE,IAAI,CAACM,KAAKC,QAAAA,WAAAA,GACrB,oBAACC,KAAGA;YAAC,KAAKD;WAAQD,OAErBL,WAAW,WAAXA,GACG,oBAAC;QAAK,WAAU;OACXD,IAAI,IAAI,gBACT,oBAACS,MAAIA;QAAC,oBAAM,oBAACC,gBAAUA;QAAK,OAAO;QAAgB,MAAM;QAAM,OAAO;UAE1E;AAIpB"}
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export declare const GroupHeading: ({ title }: {
3
+ title: string;
4
+ }) => React.JSX.Element;
@@ -0,0 +1,10 @@
1
+ import react from "react";
2
+ const GroupHeading = ({ title })=>/*#__PURE__*/ react.createElement("span", {
3
+ className: "block px-sm pb-xs pt-sm text-xs font-semibold uppercase text-neutral-muted",
4
+ style: {
5
+ letterSpacing: ".06em"
6
+ }
7
+ }, title);
8
+ export { GroupHeading };
9
+
10
+ //# sourceMappingURL=GroupHeading.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette/components/GroupHeading.js","sources":["../../../src/CommandPalette/components/GroupHeading.tsx"],"sourcesContent":["import React from \"react\";\n\nexport const GroupHeading = ({ title }: { title: string }) => (\n <span\n className=\"block px-sm pb-xs pt-sm text-xs font-semibold uppercase text-neutral-muted\"\n style={{ letterSpacing: \".06em\" }}\n >\n {title}\n </span>\n);\n"],"names":["GroupHeading","title"],"mappings":";AAEO,MAAMA,eAAe,CAAC,EAAEC,KAAK,EAAqB,iBACrD,oBAAC;QACG,WAAU;QACV,OAAO;YAAE,eAAe;QAAQ;OAE/BA"}
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export declare const HintIcon: ({ element }: {
3
+ element: React.ReactNode;
4
+ }) => React.JSX.Element;
@@ -0,0 +1,11 @@
1
+ import react from "react";
2
+ import { Icon } from "@webiny/admin-ui";
3
+ const HintIcon = ({ element })=>/*#__PURE__*/ react.createElement(Icon, {
4
+ icon: element,
5
+ color: "neutral-light",
6
+ size: "xs",
7
+ label: ""
8
+ });
9
+ export { HintIcon };
10
+
11
+ //# sourceMappingURL=HintIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette/components/HintIcon.js","sources":["../../../src/CommandPalette/components/HintIcon.tsx"],"sourcesContent":["import React from \"react\";\nimport { Icon } from \"@webiny/admin-ui\";\n\nexport const HintIcon = ({ element }: { element: React.ReactNode }) => (\n <Icon icon={element} color={\"neutral-light\"} size={\"xs\"} label={\"\"} />\n);\n"],"names":["HintIcon","element","Icon"],"mappings":";;AAGO,MAAMA,WAAW,CAAC,EAAEC,OAAO,EAAgC,iBAC9D,oBAACC,MAAIA;QAAC,MAAMD;QAAS,OAAO;QAAiB,MAAM;QAAM,OAAO"}
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export declare const Kbd: ({ children }: {
3
+ children: React.ReactNode;
4
+ }) => React.JSX.Element;
@@ -0,0 +1,14 @@
1
+ import react from "react";
2
+ const Kbd = ({ children })=>/*#__PURE__*/ react.createElement("span", {
3
+ className: "inline-flex items-center justify-center rounded-sm border border-neutral-dimmed bg-neutral-base text-xs text-neutral-muted",
4
+ style: {
5
+ minWidth: 20,
6
+ height: 20,
7
+ padding: "0 6px",
8
+ gap: 2,
9
+ fontFamily: "var(--font-family-mono, monospace)"
10
+ }
11
+ }, children);
12
+ export { Kbd };
13
+
14
+ //# sourceMappingURL=Kbd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette/components/Kbd.js","sources":["../../../src/CommandPalette/components/Kbd.tsx"],"sourcesContent":["import React from \"react\";\n\nexport const Kbd = ({ children }: { children: React.ReactNode }) => (\n <span\n className=\"inline-flex items-center justify-center rounded-sm border border-neutral-dimmed bg-neutral-base text-xs text-neutral-muted\"\n style={{\n minWidth: 20,\n height: 20,\n padding: \"0 6px\",\n gap: 2,\n fontFamily: \"var(--font-family-mono, monospace)\"\n }}\n >\n {children}\n </span>\n);\n"],"names":["Kbd","children"],"mappings":";AAEO,MAAMA,MAAM,CAAC,EAAEC,QAAQ,EAAiC,iBAC3D,oBAAC;QACG,WAAU;QACV,OAAO;YACH,UAAU;YACV,QAAQ;YACR,SAAS;YACT,KAAK;YACL,YAAY;QAChB;OAECA"}
@@ -0,0 +1,5 @@
1
+ export * from "./Kbd.js";
2
+ export * from "./HintIcon.js";
3
+ export * from "./GroupHeading.js";
4
+ export * from "./CommandItemRow.js";
5
+ export * from "./CommandDetail.js";
@@ -0,0 +1,5 @@
1
+ export * from "./Kbd.js";
2
+ export * from "./HintIcon.js";
3
+ export * from "./GroupHeading.js";
4
+ export * from "./CommandItemRow.js";
5
+ export * from "./CommandDetail.js";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Dedicated hotkey layer for the command palette. `useHotkeys` only fires handlers
3
+ * registered on the current top-most zIndex, so the palette owns its own layer.
4
+ * NOTE: components that register a higher zIndex while open will shadow `mod+k`.
5
+ * Layering interplay is revisited in a later phase.
6
+ */
7
+ export declare const PALETTE_HOTKEY_ZINDEX = 90;
8
+ export declare const NAVIGATION_GROUP = "Navigation";
@@ -0,0 +1,5 @@
1
+ const PALETTE_HOTKEY_ZINDEX = 90;
2
+ const NAVIGATION_GROUP = "Navigation";
3
+ export { NAVIGATION_GROUP, PALETTE_HOTKEY_ZINDEX };
4
+
5
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette/constants.js","sources":["../../src/CommandPalette/constants.ts"],"sourcesContent":["/**\n * Dedicated hotkey layer for the command palette. `useHotkeys` only fires handlers\n * registered on the current top-most zIndex, so the palette owns its own layer.\n * NOTE: components that register a higher zIndex while open will shadow `mod+k`.\n * Layering interplay is revisited in a later phase.\n */\nexport const PALETTE_HOTKEY_ZINDEX = 90;\n\nexport const NAVIGATION_GROUP = \"Navigation\";\n"],"names":["PALETTE_HOTKEY_ZINDEX","NAVIGATION_GROUP"],"mappings":"AAMO,MAAMA,wBAAwB;AAE9B,MAAMC,mBAAmB"}
@@ -0,0 +1,19 @@
1
+ import type { MenuConfig } from "@webiny/app-admin/config/AdminConfig/Menu.js";
2
+ import type { CommandItemVm } from "@webiny/app-admin";
3
+ import type { CommandGroup, CommandRow } from "./types.js";
4
+ /**
5
+ * Turn an is-hotkey shortcut string ("cmd+shift+m") into display chips (["⌘","⇧","M"]).
6
+ */
7
+ export declare const formatShortcut: (shortcut?: string) => string[] | undefined;
8
+ /**
9
+ * Derive Navigation rows from the registered admin menus. A navigable menu is a leaf
10
+ * `Menu.Link` (carries a `to` path + string `text`); `Menu.Item` parents/groups have
11
+ * no `to` and are skipped, but their label/icon are used for the child's section/icon.
12
+ */
13
+ export declare const deriveNavigationRows: (menus: MenuConfig[], navigateTo: (to: string) => void) => CommandRow[];
14
+ /**
15
+ * Group DI commands (from the presenter view model) by their `category` (default
16
+ * "Actions"), preserving order. Commands with a detail view show "Open" (the palette
17
+ * stays open on a sub-view); the rest show "Run".
18
+ */
19
+ export declare const commandVmsToGroups: (commands: CommandItemVm[], runCommand: (name: string) => void) => CommandGroup[];
@@ -0,0 +1,100 @@
1
+ import react from "react";
2
+ const DEFAULT_COMMAND_GROUP = "Actions";
3
+ const SHORTCUT_SYMBOLS = {
4
+ cmd: "⌘",
5
+ command: "⌘",
6
+ mod: "⌘",
7
+ ctrl: "⌃",
8
+ control: "⌃",
9
+ alt: "⌥",
10
+ option: "⌥",
11
+ shift: "⇧",
12
+ enter: "↵",
13
+ return: "↵"
14
+ };
15
+ const formatShortcut = (shortcut)=>{
16
+ if (!shortcut) return;
17
+ return shortcut.split("+").map((token)=>token.trim()).filter(Boolean).map((token)=>SHORTCUT_SYMBOLS[token.toLowerCase()] ?? token.toUpperCase());
18
+ };
19
+ const isNavigable = (element)=>{
20
+ if (!/*#__PURE__*/ react.isValidElement(element)) return false;
21
+ const props = element.props;
22
+ return "string" == typeof props.to && !!props.to && "string" == typeof props.text && !!props.text;
23
+ };
24
+ const deriveNavigationRows = (menus, navigateTo)=>{
25
+ const labelByName = new Map();
26
+ const iconByName = new Map();
27
+ const parentByName = new Map();
28
+ for (const menu of menus){
29
+ parentByName.set(menu.name, menu.parent ?? null);
30
+ const element = menu.element;
31
+ if (/*#__PURE__*/ react.isValidElement(element)) {
32
+ const props = element.props;
33
+ if ("string" == typeof props.text) labelByName.set(menu.name, props.text);
34
+ if (props.icon) iconByName.set(menu.name, props.icon);
35
+ }
36
+ }
37
+ const sectionFor = (name)=>{
38
+ const parts = [];
39
+ let parent = parentByName.get(name) ?? null;
40
+ for(let depth = 0; parent && depth < 10; depth++){
41
+ const label = labelByName.get(parent);
42
+ if (label) parts.unshift(label);
43
+ parent = parentByName.get(parent) ?? null;
44
+ }
45
+ return parts.length > 0 ? parts.join(" › ") : void 0;
46
+ };
47
+ const iconFor = (name, ownIcon)=>{
48
+ if (ownIcon) return ownIcon;
49
+ let parent = parentByName.get(name) ?? null;
50
+ for(let depth = 0; parent && depth < 10; depth++){
51
+ const icon = iconByName.get(parent);
52
+ if (icon) return icon;
53
+ parent = parentByName.get(parent) ?? null;
54
+ }
55
+ };
56
+ const rows = [];
57
+ const seenPaths = new Set();
58
+ for (const menu of menus){
59
+ if (!isNavigable(menu.element)) continue;
60
+ const { to, text, icon } = menu.element.props;
61
+ if (!seenPaths.has(to)) {
62
+ seenPaths.add(to);
63
+ rows.push({
64
+ key: menu.name,
65
+ value: `${text} ${menu.name}`.toLowerCase(),
66
+ label: text,
67
+ sub: sectionFor(menu.name),
68
+ icon: iconFor(menu.name, icon),
69
+ verb: "Open",
70
+ onRun: ()=>navigateTo(to)
71
+ });
72
+ }
73
+ }
74
+ return rows;
75
+ };
76
+ const commandVmsToGroups = (commands, runCommand)=>{
77
+ const groups = new Map();
78
+ for (const command of commands){
79
+ const category = command.category ?? DEFAULT_COMMAND_GROUP;
80
+ const rows = groups.get(category) ?? [];
81
+ rows.push({
82
+ key: command.name,
83
+ value: `${command.label} ${(command.keywords ?? []).join(" ")} ${command.name}`.toLowerCase(),
84
+ label: command.label,
85
+ sub: command.description,
86
+ icon: command.icon,
87
+ shortcut: formatShortcut(command.shortcut),
88
+ verb: command.hasDetailView ? "Open" : "Run",
89
+ onRun: ()=>runCommand(command.name)
90
+ });
91
+ groups.set(category, rows);
92
+ }
93
+ return Array.from(groups, ([title, rows])=>({
94
+ title,
95
+ rows
96
+ }));
97
+ };
98
+ export { commandVmsToGroups, deriveNavigationRows, formatShortcut };
99
+
100
+ //# sourceMappingURL=deriveRows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette/deriveRows.js","sources":["../../src/CommandPalette/deriveRows.tsx"],"sourcesContent":["import React from \"react\";\nimport type { MenuConfig } from \"@webiny/app-admin/config/AdminConfig/Menu.js\";\nimport type { CommandItemVm } from \"@webiny/app-admin\";\nimport type { CommandGroup, CommandRow } from \"./types.js\";\n\nconst DEFAULT_COMMAND_GROUP = \"Actions\";\n\nconst SHORTCUT_SYMBOLS: Record<string, string> = {\n cmd: \"⌘\",\n command: \"⌘\",\n mod: \"⌘\",\n ctrl: \"⌃\",\n control: \"⌃\",\n alt: \"⌥\",\n option: \"⌥\",\n shift: \"⇧\",\n enter: \"↵\",\n return: \"↵\"\n};\n\n/**\n * Turn an is-hotkey shortcut string (\"cmd+shift+m\") into display chips ([\"⌘\",\"⇧\",\"M\"]).\n */\nexport const formatShortcut = (shortcut?: string): string[] | undefined => {\n if (!shortcut) {\n return undefined;\n }\n return shortcut\n .split(\"+\")\n .map(token => token.trim())\n .filter(Boolean)\n .map(token => SHORTCUT_SYMBOLS[token.toLowerCase()] ?? token.toUpperCase());\n};\n\nconst isNavigable = (\n element: unknown\n): element is React.ReactElement<{ to: string; text: string; icon?: React.ReactNode }> => {\n if (!React.isValidElement(element)) {\n return false;\n }\n const props = element.props as { to?: unknown; text?: unknown };\n return (\n typeof props.to === \"string\" && !!props.to && typeof props.text === \"string\" && !!props.text\n );\n};\n\n/**\n * Derive Navigation rows from the registered admin menus. A navigable menu is a leaf\n * `Menu.Link` (carries a `to` path + string `text`); `Menu.Item` parents/groups have\n * no `to` and are skipped, but their label/icon are used for the child's section/icon.\n */\nexport const deriveNavigationRows = (\n menus: MenuConfig[],\n navigateTo: (to: string) => void\n): CommandRow[] => {\n const labelByName = new Map<string, string>();\n const iconByName = new Map<string, React.ReactNode>();\n const parentByName = new Map<string, string | null>();\n for (const menu of menus) {\n parentByName.set(menu.name, menu.parent ?? null);\n const element = menu.element;\n if (React.isValidElement(element)) {\n const props = element.props as { text?: unknown; icon?: React.ReactNode };\n if (typeof props.text === \"string\") {\n labelByName.set(menu.name, props.text);\n }\n if (props.icon) {\n iconByName.set(menu.name, props.icon);\n }\n }\n }\n\n // Full ancestor breadcrumb (\"Settings › System\"), so same-named leaves under\n // different sections (e.g. the File Manager app vs. its settings page) are\n // distinguishable. Depth-guarded against malformed parent cycles.\n const sectionFor = (name: string): string | undefined => {\n const parts: string[] = [];\n let parent = parentByName.get(name) ?? null;\n for (let depth = 0; parent && depth < 10; depth++) {\n const label = labelByName.get(parent);\n if (label) {\n parts.unshift(label);\n }\n parent = parentByName.get(parent) ?? null;\n }\n return parts.length > 0 ? parts.join(\" › \") : undefined;\n };\n\n // Leaf items often carry no icon of their own; walk up to the nearest ancestor\n // that has one (a group may be icon-less, but the section root usually isn't).\n const iconFor = (name: string, ownIcon?: React.ReactNode): React.ReactNode | undefined => {\n if (ownIcon) {\n return ownIcon;\n }\n let parent = parentByName.get(name) ?? null;\n for (let depth = 0; parent && depth < 10; depth++) {\n const icon = iconByName.get(parent);\n if (icon) {\n return icon;\n }\n parent = parentByName.get(parent) ?? null;\n }\n return undefined;\n };\n\n const rows: CommandRow[] = [];\n const seenPaths = new Set<string>();\n for (const menu of menus) {\n if (!isNavigable(menu.element)) {\n continue;\n }\n const { to, text, icon } = menu.element.props;\n // Skip exact duplicate destinations (same path registered more than once).\n if (seenPaths.has(to)) {\n continue;\n }\n seenPaths.add(to);\n\n rows.push({\n key: menu.name,\n value: `${text} ${menu.name}`.toLowerCase(),\n label: text,\n sub: sectionFor(menu.name),\n icon: iconFor(menu.name, icon),\n verb: \"Open\",\n onRun: () => navigateTo(to)\n });\n }\n return rows;\n};\n\n/**\n * Group DI commands (from the presenter view model) by their `category` (default\n * \"Actions\"), preserving order. Commands with a detail view show \"Open\" (the palette\n * stays open on a sub-view); the rest show \"Run\".\n */\nexport const commandVmsToGroups = (\n commands: CommandItemVm[],\n runCommand: (name: string) => void\n): CommandGroup[] => {\n const groups = new Map<string, CommandRow[]>();\n for (const command of commands) {\n const category = command.category ?? DEFAULT_COMMAND_GROUP;\n const rows = groups.get(category) ?? [];\n rows.push({\n key: command.name,\n value: `${command.label} ${(command.keywords ?? []).join(\" \")} ${command.name}`.toLowerCase(),\n label: command.label,\n sub: command.description,\n icon: command.icon,\n shortcut: formatShortcut(command.shortcut),\n verb: command.hasDetailView ? \"Open\" : \"Run\",\n onRun: () => runCommand(command.name)\n });\n groups.set(category, rows);\n }\n return Array.from(groups, ([title, rows]) => ({ title, rows }));\n};\n"],"names":["DEFAULT_COMMAND_GROUP","SHORTCUT_SYMBOLS","formatShortcut","shortcut","token","Boolean","isNavigable","element","React","props","deriveNavigationRows","menus","navigateTo","labelByName","Map","iconByName","parentByName","menu","sectionFor","name","parts","parent","depth","label","undefined","iconFor","ownIcon","icon","rows","seenPaths","Set","to","text","commandVmsToGroups","commands","runCommand","groups","command","category","Array","title"],"mappings":"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"}
@@ -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
@@ -1,3 +1,3 @@
1
1
  import React from "react";
2
- declare const Welcome: () => React.JSX.Element | null;
2
+ declare const Welcome: () => React.JSX.Element;
3
3
  export default Welcome;